140 likes | 159 Views
Explore the process of obfuscating C++ source code using opaque predicates to protect intellectual property and hinder reverse engineering. Learn about implementation details, obfuscation examples, and measuring obfuscation quality.
E N D
Code Obfuscation Final Presentation Yakkob Iyun Guided by Eitan Koch
Topics to be discussed • Problem Definition • Project Purpose – Building Obfuscator • Obfuscation Using Opaque Predicates • Implementation details • Obfuscation example • Obfuscation Quality and Measurements
Problem Definition • Modern programming languages generate output files (binaries , byte code files ect.) that can be reversed engineered easily. We need to Defend our intellectual property in a way that minimizes the additional overhead resources Solution : Obfuscation!!!
Project purpose - Building Obfuscator • Creating an application that for a given C++ source code , generates an obfuscated one that has the exact same functionality as the original one. Compilation Output Source code Internet (Server – Client) Decopmilation Obfuscated Source code Obfuscated Source code Application Execute Deobfuscation Compilation Output Source code
Obfuscation Using Opaque Predicates • Known fact : Adding junctions makes our life harder So we will obfuscate our code by adding If-else structures with Opaque Predicates in order to complicate the control flow of the code.
Opaque Predicate • Opaque Predicate : an expression that evaluates to either "true" or "false“ , which its outcome is known to the obfuscator and is very difficult and even impossible for the deobfuscator to evaluate , without running the application itself. T Dead Code Opaque Predicate Benefits: Increased number of predicates to deduce Inserting Dead and irrelevant code to confuse an attacker.
Opaque Predicate Manufacture: Opaque Predicate Benefits: • Introduce an obfuscated Graph class to the code. • Introduce a code that manipulates (build and changes) the Graph. • Building Opaque Predicate with user input names according to specific invariants that the graph structure holds. • Adding Randomness for the IF conditions together with the predicate. • The Introduced Graph Class code and the code that manipulates the Graph , blends well with the source code because it uses user input names . • The predicate names are user defined so they resemble the given code. • The added predicate are easily to deduce by the obfuscator but hard to deduce by the deobfuscator. • In Run Time the behavior is not deterministic.
Application Use details • Input : User prepares config file , to configure parameters for the Opaque predicate inserting , and the “String” option that replaces given tokens with random tokens /**************************************************************/ /* Configuration File For Koby's Obfuscation App */ /**************************************************************/ /* Working Folder */ WorkingFolder=C:\Users\koby\Desktop\New folder /* Source Files */ SourceFileList=folder.cpp /********************************************/ /* Parameters for "Opaque" Option */ /********************************************/ /* Related Project Names */ RelatedProjectNames=melody,tune,volume,artist, singer /* Number Of Predicates To Add */ NumberOfPredicatesToAdd=2 /* Function Names To Insert The Predicates */ FunctionNamesToInsertThePredicates=Play_Song /********************************************/ /* Parameters for "Strings" Option */ /*******************************************/ /* Function Names To Be Obuscated */ FunctionNamesToBeObuscated=Play_Song, Print_Folder_Songs /* Variable Names */ VariableNames=Folder,song_name,temp_song
Obfuscation example Original Code bool Folder::Print_Folder_Songs (const string& curr_artist_name) // not checked {Iterator<Song> itr =songs_list.GetIterator(); Song temp_song; if (curr_artist_name=="temp_not_given") {while (itr.HasNext()) {itr.Next().Print_Song_Name();}} else {while (itr.HasNext()) {temp_song=itr.Next(); if (temp_song.Get_Artist_Name()==curr_artist_name) {temp_song.Print_Song_Name();}}} return true;} bool Folder::Play_Song (const string& song_name) {Song curr_song; Iterator<Song> itr =songs_list.GetIterator(); bool found=false; while (itr.HasNext()&&(!found)) {curr_song=itr.Next(); if (curr_song.song_name==song_name) {curr_song.Play_Song(); found=true;}} return found;}
Obfuscation example bool Folder::Print_Folder_Songs (const string& curr_artist_name) // not checked {Iterator<Song> itr =songs_list.GetIterator(); Song temp_song; if (curr_artist_name=="temp_not_given") {while (itr.HasNext()) {itr.Next().Print_Song_Name();}} else {while (itr.HasNext()) {temp_song=itr.Next(); if (temp_song.Get_Artist_Name()==curr_artist_name) {temp_song.Print_Song_Name();}}} return true;} bool Folder::Play_Song (const string& song_name) {Song curr_song; srand (time(NULL) ); artist* melody = new artist(); melody->singer(); melody= melody->__singer(); melody->singer(); melody= melody->__singer(); melody->singer(); melody->singer(); melody->___tune(); melody= melody->__singer(); melody->singer(); melody->singer(); melody->___tune(); melody= melody->__singer(); melody->singer(); melody->singer(); melody->___tune(); artist* tune; tune=melody->__artist(); tune->singer(); tune = tune->__singer(); tune->singer(); melody->singer();tune->singer(); tune = tune->__singer(); tune->singer(); melody->singer(); melody= melody->__singer(); tune->___tune(); melody->singer(); melody->singer(); melody->___tune(); if (melody->__volume(tune) ) { artist* melody = new artist(); melody->singer(); melody= melody->__singer(); melody->singer(); melody= melody->__singer(); melody->singer(); melody->singer(); melody->___tune(); melody= melody->__singer(); melody->singer(); melody->singer(); melody->___tune(); melody= melody->__singer(); melody->singer(); melody->singer(); melody->___tune(); artist* tune; tune=melody->__artist(); tune->singer(); tune = tune->__singer(); tune->singer(); melody->singer();tune->singer(); tune = tune->__singer(); tune->singer(); melody->singer(); melody= melody->__singer(); tune->___tune(); melody->singer(); melody->singer(); melody->___tune(); Obfuscated Code – Opaque Option tune1: int tune2 = rand() % 2; if (melody->__volume(tune) && tune2) { tune->singer(); melody->singer();tune->singer(); tune = tune->__singer(); tune->singer(); melody->singer(); melody= melody->__singer(); tune->___tune(); melody->singer(); melody->singer(); goto tune1; melody->___tune(); } tune->singer(); melody->singer(); melody->singer(); melody->___tune(); } Iterator<Song> itr =songs_list.GetIterator(); bool found=false; while (itr.HasNext()&&(!found)) {curr_song=itr.Next(); if (curr_song.song_name==song_name) {curr_song.Play_Song(); found=true;}} return found;}
Obfuscation example Obfuscated Code – Opaque Option + String Option #include "folder.h" #include "_include_.h" /* implementation of class ____18960____ */ //private methods bool ____18960___::__17385___(const string& curr___28814___name) // not checked {Iterator<Song> itr =songs_list.GetIterator(); Song ____237____; if (curr_____28814_____name=="temp_not_given") {while (itr.HasNext()) {itr.Next().Print_Song_Name();}} else {while (itr.HasNext()) {____237____=itr.Next(); if (____237____.Get_Artist_Name()==curr_____28814_____name) {____237____.Print_Song_Name();}}} return true;} bool ____18960____::____4251____ (const string& ____8667____) {Song curr_song; srand (time(NULL) ); ____28814____* ____15463____ = new ____28814____(); ____15463____->____13731____(); ____15463____= ____15463____->______13731____(); ____15463____->____13731____(); ____15463____= ____15463____->______13731____(); ____15463____->____13731____(); ____15463____->____13731____(); ____15463____->_______9449____(); ____15463____= ____15463____->______13731____(); ____15463____->____13731____(); ____15463____->____13731____(); ____15463____->_______9449____(); ____15463____= ____15463____->______13731____(); ____15463____->____13731____(); ____15463____->_______9449____(); ____28814____* ____9449____; ____9449____=____15463____->______28814____(); ____9449____->____13731____(); ____9449____ = ____9449____->______13731____(); ____9449____->____13731____(); ____15463____->____13731____();____9449____->____13731____(); ____9449____ = ____9449____->______13731____(); ____9449____->____13731____(); ____15463____->____13731____(); ____15463____= ____15463____->______13731____(); ____9449____->_______9449____(); ____15463____->____13731____(); ____15463____->____13731____(); ____15463____->_______9449____(); if (____15463____->______10535____(____9449____)) { ____28814____* ____15463____ = new ____28814____(); ____15463____->____13731____(); ____15463____= ____15463____->______13731____(); ____15463____->____13731____(); ____15463____= ____15463____->______13731____(); ____15463____->____13731____(); ____15463____->____13731____(); ____15463____->_______9449____(); ____15463____= ____15463____->______13731____(); ____15463____->____13731____(); ____15463____->____13731____(); ____15463____->_______9449____(); ____15463____= ____15463____->______13731____(); ____15463____->____13731____(); ____15463____->____13731____(); ____15463____->_______9449____(); ____28814____* ____9449____; ____9449____=____15463____->______28814____(); ____9449____->____13731____();
Obfuscation Quality and Measurements • Mccabe metric (Cyclomatic complexity) – known metric that trys to measure code complexity. • The cyclomatic complexity of a section of source code is the count of the number of linearly independent paths through the source code.
Obfuscation Quality and Measurements How to compute the “Cyclomatic complexity”: Build control flow graph of the program , and the compute: • E − N + 2P Where E = the number of edges of the graph N = the number of nodes of the graph P = the number of connected components • Note that for a program without any IF statements or WHILE, FOR , CASE statements the Cyclomatic complexity is 1 Cyclomatic complexity = 9 - 8 + 2 = 3
Obfuscation Quality and Measurements Experiments Results I used the “CCCC” freeware to compute the cyclomatic complexity on the Obfuscation example given in the previous sides