2. 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
4. 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, …
5. 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,…
6.
7. 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
9. 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
10. Typical Attacks
• Search for patterns
• Statically
• Dynamically
• Deactivation of the RESPOND
• Modification of the condition
• Pre-processing the new hash value
11. 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)
12. 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;
}
15. 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) = x2 + 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)
16.
17. 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
18. Step One
• ModulePass, IR code, go through all the
program
• …
19.
20. Step One
• ModulePass, IR code, go through all the
program
• Create multiple check functions
• Pool of functions
• Random names
• ...
22. 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
• ...
24. 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
27. 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
28. Solutions
• Use static array
• Get the value at a certain address
•
SwitchV ar = tab[0] res1 res2 ... resn
• Post-process the binary file
• Python script
• PyElfTool
29. 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
30. 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
31. 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
33. // Module test.c
int foo(int a) {
return a+2;
}
float bar(float a) {
return a+2.0;
}
34. // 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;
}
35. 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
36. 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
37. • 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
38. 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
39. • 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
}
40. 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
41. • 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
]
42. 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
44. 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
45. • 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
46. • We still have some problems
• Inter-module calls
• Distribution of an obfuscated library
• API breakage
48. Conclusion - Function
merging
• Use strip!
• Fonctions name give a lot of informations
• Use it with other obfuscations
49. Tests
• Test suite
• LibTomCrypt
• OpenSSL
• SQLite (+200’000 tests)
• Obfuscation of ALL the code
• Global idea of the consequences
50. 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”