Técnicas anti-ingeniería inversa

9. Técnicas anti-ingeniería
inversa
DR. MIGUEL ÁNGEL OROS HERNÁNDEZ
Técnicas antiingeniería
inversa
1.
¿Qué es anti-ingeniería inversa?
2. Enfoques
3. Encriptación de código
4. Técnicas anti-depuración
5. Transformaciones de control de
flujo
6. Transformación de datos
¿Qué es anti-ingeniería inversa?
¿Qué es anti-ingeniería inversa?
 Regardless of which application
 No for open source software
 Then, consider introducing some form of
antireversing
 Some software development platforms really
necessitate some form of antiversing measures:
bytecode-based platforms such as Java and .NET
Enfoques
Enfoques
Eliminating Symbolic Information
Obfuscating the Program
 Eliminate any obvious textual
 Generic name for a number of
information from the program
 In a regular non-bytecode-based
compiled program, this simply
means to strip all symbolic
information from the program
executable
 In bytecode-base programs, the
executables often contain large
amount of internal symbolic
information such as class names,
class member names, and the
names of instantiated global
objects
techniques that are aimed at
reducing the program’s
vulnerability to any kind of static
analysis
 Modify the program¿s layout,
logic, data, and organization in a
way that keeps it functionality
identical yer far less readable
¿Qué es anti-ingeniería inversa?
Basic approaches to antireversing
Embedding Antidebugger Code
 Idea: have the program intentionally perform
operations that would somehow damage or disable a
debugger, if one is attached
 One approach: detect the debugger and terminate
the program
Encriptación de código
Encriptación de código
 Common method for
preventing static analysis
 Encrypting the program at
some point after it is
compiled
 Embedding some sort of
decription code inside the
executable
 The program must decrypt
the code in runtime before it
is executed
 For the skill full reverser,
there is not an incovenience
 Everything required for the
decryption of the program
must reside inside the
executable (decryption logic
and decryption key)
 Use ofr unpacker programs
creates a new executable
that contains the original
program minus the
encryption
Encriptación de código
improvements
1.
Try and hide the key within the program
2. Use separate hardware that stores the decryption key or
actually performs the decryption
3. Use a key that is calculated in runtime, inside the
program. Such a key-generation algorithm could easily be
designed that would require a remarkably sophisticaded
unpacker
Técnicas anti-depuración
Técnicas anti-depuración
 A large part of the
reversing process often
takes place inside a
debugger
 So, incorporate special
code in the program that
prevents or complicates
the process of stepping
through the program and
placing breakpoints in it
 Effectiveness of
antidebugger techniques


Antibugger techniques +
code encryption
Allows the program to
decrypt itselt
Transformadores de control de
flujo
Transformaciones de control de flujo
 Alter the order and flow of a program in a way that
reduces its human readability
 Categories:

Computation transformations

Aggregation transformations

Ordering transformations
Transformaciones de control de flujo
computation transformations
 Aimed at reducing the readability of the code by
modifying the program’s original control flow
structure in ways that make for a funcionally
equivant program that is far more difficult to
translate back into a high-level language
 How?
 Removing control flow information from the program,. Or

Adding new control flow statements that complicate the
program and cannot be easily translated into a high-level
alnguage
Transformaciones de control de flujo
Agregation transformations
 Destroy the high-level structure of the program by
breaking the high-level abstractions created by the
programmer while the program was being written
 Idea

Break such abstractions so that the high-level organization of
the code becomes senseless
Transformaciones de control de flujo
Ordering transformations
 Less powerful transformations
 Randomize, as much as possible, the order of
operations in a program so that its readability is
reduced
Transformaciones de control de flujo
Opaque Predicates
 Idea: create a logical statement whose outcome is
constant and known in advance

if (x + 1) == x

Is the condition satisfied?
Used to confuse reversers and automated decompilation tools

 Objetive: create opaque predicates that would be
difficult to distinguish from the actual program code
and whose behavior would be difficult to predict
without actually stepping into the code
Transformaciones de control de flujo
Confusing Decompilers
 There exists decompilers for bytecode executables
 Use of obfuscators
confuse decompilers, so the code cannot be easily restored to a
highly detailed source code
 One trick: modify the program binary so that the
bytecode contains statements that cannot be
translated back into the original high-level language
Java does not have the goto statment, but Java bytecode does
Transformaciones de control de flujo
Table Interpretation
 Converting a program or a function into a table
interpretation layout is a highly powerful obfuscation
approach
 Idea
 Break a code sequence into multiple short chunks and have the
code loop through a conditional code sequence that decides to
which of the code sequences to jump at any given moment
 Reduces the readability of the code because it hides
any kind of structure within it
Transformaciones de control de flujo
Inlining and Outlining
Inlining
 A compiler optimization
technique
 The functions are
duplicated to any place in
the program that calls them
 Instead of having all callers
call into a single copy, the
compiler replaces every call
into the function with an
actual in-place copy of it
 Improves runtime
performance
 It eliminates the internal
abstractions created by the
software developer
 Enhancement
Inlining + Outlining
Transformaciones de control de flujo
Inlining: example
int pred(int x) {
if (x == 0)
return 0;
else
return x - 1;
}
Before inlining:
int f(int y) {
return pred(y) +
pred(0) +
pred(y+1);
}
Transformaciones de control de flujo
Inlining: example
 After inlining
int f(int y) {
int temp = 0;
if (y == 0) temp += 0;
else temp += y - 1; /* (1) */
if (0 == 0) temp += 0;
else temp += 0 - 1; /* (2) */
if (y+1 == 0) temp += 0;
else temp += (y + 1) - 1; /* (3) */
return temp;
}
Transformaciones de control de flujo
Inlining and Outlining
Outlining
 Means that you take a certain code sequence that
belongs in one function and create a new function
that contains just that sequence
 Outlining is opposite of inlining
Transformaciones de control de flujo
Interleaving Code
 A reasonably effective obfuscation technique
 Idea
You take two or more functiions and interleave their
implementations so that they become exceedingly difficult to
read
Transformaciones de control de flujo
Interleaving Code
Function1()
{
Function1_Segment1;
Function1_Segment2;
Function1_Segment3;
}
Function2()
{
Function2_Segment1;
Function2_Segment2;
Function2_Segment3;
}
Transformaciones de control de flujo
Interleaving Code
Function3()
{
Function3_Segment1;
Function3_Segment2;
Function3_Segment3;
}
Transformaciones de control de flujo
Interleaving Code
Function1_Segment3;
End of Function1
Function1_Segment1; (This is the
Function1 entry-point)
Opaque Predicate -> Always jumps to
Function1_Segment2
Function3_Segment2;
Opaque Predicate -> Always jumps to
Segment3
Transformaciones de control de flujo
Interleaving Code
Function3_Segment1; (This is the Function3
entry-point)
Opaque Predicate -> Always jumps to
Function3_Segment2
Function2_Segment2;
Opaque Predicate -> Always jumps to
Function2_Segment3
Function1_Segment2;
Opaque Predicate -> Always jumps to
Function1_Segment3
Transformaciones de control de flujo
Interleaving Code
Function2_Segment3;
End of Function2
Function3_Segment3;
End of Function3
Function2_Segment1; (This is the
Function2 entry-point)
Opaque Predicate -> Always jumps to
Function2_Segment2
Transformaciones de control de flujo
Ordering Transformations
 Shuffling the order of operations in a program is a
free decently effective method for confusing
reversers
 Idea


Simply randomize the order of operations in a functioin as
much as possible
Find operations that are not codependent and completely
randomize their order
Transformaciones de datos
Transformaciones de datos
 Data transformation are obfuscation transformations
that focus on obfuscating the program’s data rather
the program’s structure
 Data transformations also boil down to code
modifications
Transformaciones de datos
Modifying Variable Encoding
 Modify the encoding of some or all program
variables
 Confuse reversers because the intuitive meaninings
of variable values will not be immediately clear
 Example: simply shift it by one bit to the left


For (int i = 1; i < 100; i++)
For (int i = 2; i < 200; i += 2)
Transformaciones de datos
Restructuring Arrays
 Means that you modify the layout of some arrays in a
way that preserves their original functionality but
confuses reversers with regard to their purpose
 Many different forms to this transformation

Merging more than one array into one large array

Break one array down into several smaller arrays

Change the number of dimensions in an array
 Reversing: Secrets of Reverse
Engineering
Bibliografía



Eldad Eilam
Wiley Publishing, Inc.
2005
Fin