CEN429 Secure Programming¶
Week-4¶
Code Hardening Techniques¶
Download
Outline¶
- Code Hardening Techniques
- Code Hardening for Native C/C++
- Code Hardening for Java and Interpreted Languages
Week-4: Code Hardening Techniques¶
1. Code Hardening Techniques for Native C/C++¶
In low-level languages like C and C++, various techniques are used to write secure code and make it resistant to attacks. These techniques aim to make code analysis and reverse engineering more difficult.
a) Opaque Loops¶
Theoretical Explanation: Opaque loops are loops that, when viewed externally, have no clear purpose. These loops make code analysis more difficult. Attackers struggle to understand the function of the loop, making the code harder to reverse-engineer.
Example Applications:
- Adding loops created with random conditions to complicate code analysis.
- Introducing loops that do not affect program functionality but confuse the analysis.
- Using opaque loops to increase program runtime, misleading attackers.
b) Hiding Shared Object Symbols¶
Theoretical Explanation: Hiding symbols used in shared objects makes external access to these objects difficult. This process is used to prevent analysis and reverse engineering.
Example Applications:
- Restricting symbol visibility with compiler options.
- Only exposing necessary symbols and hiding others to improve security.
- Concealing critical functions in shared libraries to enhance protection.
c) Obfuscation of Arithmetic Instructions¶
Theoretical Explanation: Arithmetic operations are fundamental to a program. Making these operations more complex makes the code harder to analyze and understand.
Example Applications:
- Replacing simple addition operations with more complex mathematical expressions.
- Adding unnecessary steps to arithmetic operations to maintain functionality while complicating code analysis.
- Using bit manipulation on arithmetic operations to make them more complex.
d) Obfuscation of Function Names¶
Theoretical Explanation: Changing function names to random character strings makes the code harder to understand. This technique is especially useful for preventing reverse engineering.
Example Applications:
- Changing function names to meaningless strings of characters.
- Generating different function names for each compilation to confuse static analysis tools.
- Randomizing critical function names to make them difficult for attackers to identify.
e) Obfuscation of Source File Names¶
Theoretical Explanation: Obfuscating source file names makes it difficult to understand which function or class the file belongs to.
Example Applications:
- Changing source file names to random characters.
- Hiding relationships between source files to obscure code structure.
- Obfuscating file names without affecting the source code by modifying structures.
f) Obfuscation of Static Strings¶
Theoretical Explanation: Static strings are important information sources for attackers. Encrypting and hiding these strings increases code security.
Example Applications:
- Encrypting static strings and decrypting them at runtime.
- Applying random string masks to obscure the meaning of the strings.
- Reducing static string usage by eliminating string constants.
g) Other Code Hardening Techniques¶
- Opaque Boolean Variables: Making conditional statements more complex.
- Function Boolean Return Codes: Making function return values more complex.
- Obfuscation of Function Parameters: Hiding function parameters.
- Bogus Function Parameters & Operations: Adding meaningless parameters and operations to complicate analysis.
- Control Flow Flattening: Flattening control flow to make it unpredictable.
- Randomized Exit Points: Randomizing exit points to reduce code predictability.
- Logging Disabled on Release: Disabling logging in the final release version.
2. Code Hardening Techniques for Java and Interpreted Languages¶
In Java and other interpreted languages, code hardening techniques are used to reduce security vulnerabilities and complicate reverse engineering efforts.
a) Code Obfuscation and Shrink Protection with Proguard¶
Theoretical Explanation: Proguard shrinks, optimizes, and obfuscates Java code, making it harder to analyze.
Example Applications:
- Using a Proguard configuration file to shrink and optimize the code.
- Testing obfuscated code and resolving errors.
- Analyzing Proguard reports to identify which elements have been obfuscated.
b) Separated Fingerprint Storage for Device Binding¶
Theoretical Explanation: This technique uses a device's unique properties to ensure that the application only runs on specific devices.
Example Applications:
- Encrypting the device fingerprint and storing it securely.
- Using fingerprint verification to ensure the application runs on the designated device.
- Protecting fingerprint data from attacks.
c) Native Library JNI API Obfuscation¶
Theoretical Explanation: Obfuscating native libraries called through the Java Native Interface (JNI) makes reverse engineering more difficult.
Example Applications:
- Randomizing JNI function names.
- Hiding JNI parameters to complicate understanding.
- Using error management in JNI to prevent attackers from analyzing errors.
d) Obfuscation of Static Strings¶
Theoretical Explanation: Static strings contain important information that attackers can use during reverse engineering. Obfuscating these strings increases security.
Example Applications:
- Encrypting static strings and decrypting them at runtime.
- Obfuscating strings to obscure their meaning.
- Using random string generation and manipulation techniques to enhance security.
Summary of the Week and Next Week¶
This Week:¶
- Code Hardening Techniques (C/C++ and Java)
- Obfuscation Techniques and Applications
Next Week:¶
- Attack Trees and Security Models
- Attack Methods and Secure Communication