
we have UJ we will be giving a talk on off you station please give them your attention throughout the entire throughout the entire talk thank you oh hi everyone thank you for coming to my talk on an effective approach to solve for occupation so before we get to the main idea which is the idea of how to effectively implement occupation let's first understand what software education is so what is software application software application is a software protection mechanism that is performed through program transformation and this transformation has two main side effects first it makes a corresponding executable binary more difficult to analyze and second is I perform that first step without changing programs core functionalities so this definition
is still very textbook like so we can we can break it down a little bit more what do we mean by more difficult to analyze and this difficult aspect is actually made up of three distinct properties potency restaurants and stealth and Christian Kohlberg is is actually the first person that used those three properties to assess the quality of an occupation transformation or application technique so what are these three properties done so on one hand potency is a measure measure the strength of the transformation against automated analysis and automated analysis as in a person sitting from computer like myself actively trying to figure out how to undo the transformation with traditional torn like a disassembly such as 4.28
Oprah Gita binary ninja that can take an executable and zero and one and display its content in human readable form and usually that human readable form and tells the instruction that's contained within the executable binary and usually we call that the disassembly and so the data that the instruction use so presided disassembler another popular tool is also the debugger such as gdb that can take a snippet of this assemble target help an analyst verify a snippet of disassembly and verify as in verify the runtime behavior so the stronger the potency the harder it is for an analyst to understand that this assembly that is displayed by this assembler or to verify the runtime behavior with the help of a
debugger and on the other hand restaurants measure the strength of the transformation against automated analysis and automated analysis is just like myself again sitting in front of a computer press a button and boom the transformation is undone and some automated example automated analysis tools are anger being said BAP and b2 r2 and actually in particular being SEC has the capability to undo a transformation called opaque predicates and things Agnew is basically a terminal program underlined in blue is the command you type to a terminal to invoke being SEC on an executable binary code and Graham underscore all LLVM and underlines yellow is basically the output from pin SEC that will actually accurately identify the opaque predicates in that
executable binary and lastly stealth.stealth measure the strength of the transformation against initial detection so essentially it just just how well the transform coat blends in with the original authentic code so the stronger the stealth property the harder it is to differentiate between the transform code and original code so with the knowledge that oops sorry oh sorry so one picked extinct distinction that I must made is our software application it's not the same as cryptography the protection offers/buy software application does not have the same mathematical guarantees as cryptography so for example we cannot make statements such as it will take 2000 years of a 2.2 single-core CPU to undo the set transformation in other word the
strength of the transformation three properties that we'll just discuss this discussed earlier the strength of each one can be introduced so with the knowledge that we can never make a computation impossible in one's lifetime to undo a oxidation transformation the one that we know now or the one that we might discover in the future perhaps us a better or more precise term but what we meant by more difficult to analyze and really that precise term is time consuming essentially we can only hope to make an oxidation technique more time-consuming for an analyst to undo so ultimately the transformations three properties that made up this time-consuming aspect combine to answer the question of how much more
time-consuming that this transformation makes in full reverse engineering at the end of the day we really just want to make the analyst gives up and software application achieve this not by making the information that protects impossible to uncover software application achieve this by making the process of uncovering this information so time-consuming that the analyst eventually gives up so now the question is how do we make them maximize this time-consuming aspect and to answer that let's look at the the occupation process because really this generic deification process actually Maps really well to the three properties that we just discussed earlier so for the application usually the first step is that we want to identify the occupation technique and the ability for
an analyst to perform this step really depends on the stealth property so the stronger the stealth property the harder it is to perform this step and after we identified the occupation technique now then we can perform the relevant the occupation step and the ability for analysts perform this step really depends on the potency and residents property so the stronger the potency in residents the harder is to perform this second step and if we look at modern occupation technique really what we see is that they only focus on the second step of the occupation process so they only focus on making the potency and residents property stronger well given little to no regards on the stealth property in summary modern
occupation are noisy and they're noisy because they are easy to identify and the root cause of that is really because they have low stealth so let's take a look at an example of an modern altercation technique called control photograph flattening so before we get to the theory of how this occupation technique work let's first understand what a control flow graph or abbreviated CFG is so a CFG is a representation of a function disassembly where the program flow is also encoded and how is able to encode program flow into its representation in slightly represent disassembly in basic blocks and use arrows connecting two different basic blocks to represent a control flow and a basic plot basically has one unique
entrance point and one unique exit point so once you enter a basic block you will always execute the same sequence of instruction so this means that if the disassembly contains like a control flow ordering instruction like an if statement then this assembly and the CFG representation will be split into multiple basic block as shown in this picture here so in this picture based the top basic block ends with an if statement and if the if statement evaluates to true it will go to the basic block at where the green arrows is pointing and if it evaluates to false it will go to the basic block where the red arrow pointing so why does this representation
useful then well in this representation it actually increases that this Assembly's glens value with the ability to quickly glance over the disassembly and have some sort of understanding of what the co is doing and to be more precise one can recognize high-level programming constructs such as the if statement actually explained earlier while loop for loop and also switched statement by just a quick glance of the disassembly so what does this particular oxidation technique do is that it remove the increased glance value that the CFG representation provides such as the shape indicating high level programming to construct as discussed earlier and also just any type of inference that analysts can make by just how close the
basic block is to one another and how its able to do so is that it it transform every possible control flow graph an example show to the left into the into the one shown to the right and how able to do so is I takes each original basic block from the original CFG starting at the bottom of the new CFG and then a dispatcher that chooses which original CFG to go to so essentially post occupation by this particular transformation will make every control flow graph look like this so why this is I have no stealth well that's because all the transform CFG will have that particular distinctive shape so modern education is noisy they are easy to identify because they have
love stealth but doesn't matter it shouldn't matter if that the application process still takes a long time right well the problem with that way of thinking is that real world implementation leaves behind very distinctive footprint to allow for tor pacific or non generic approach to the application let's take a look at all LLVM implementation of control flow graph flattening so all of VM is a publicly available applicator that you can just find on github so an example transform comb bio LVM is shown in that particular CFG so in OPM an original basic block will always end up with setting the same local variable to a constant that tells the dispatcher was the next original basic block that they
should execute next this means that once we figure out the content that correspond to each of the original basic block that's flatting at the bottom then now allow us to just quickly reconstruct the original CFG so what's the solution how do we effectively implement occupation then well instead of focusing on making the altercation technique harder to break also focus on making it harder to identify so instead of just focus on this potency and wrestling's property don't forget the stealth property respect each property that makes up this time-consuming aspect and perhaps to drive the importance of this stealth property even more it might be better for us to also think of a higher level what's more frustrating understanding
what the problem is but now how to solve it well with the availability of the world wide web you know there's bound to be solution online the self-similar problem so learn the general approach to tackle those problems and use it to tackle the one you have a hands how about not understanding or even aware of what the problem is well in that case it's really not anything I can do right so if an analyst is now aware of what is oxic ated it makes that person makes the run assumption about what the co is doing and once you make the wrong assumption it also makes them fall deeper into this rabbit hole and in the
context of reverse engineering we usually call out the reversing help which is spending days weeks hopefully not month but probably of analyzing the same executable binary without understanding anything about what the internal is how the internal is implemented and really out of three properties that make up this time-consuming aspect only the stealth property can achieve this idea of making the analyst make the wrong assumption about what the co is doing so to end this talk I will give a more concrete example and under importance of the stealth property so recently I was studying an application technique called opaque predicate and during my research I discovered the assumption that either pro makes when tries to I automatically
identify opaque predicates and I was able to utilize our assumption to make stealthy opaque predicates when it's analyzed under either Pro so just a little background opaque predicate belongs to disassembly desynchronization and thus assembly distinct translation is basically an umbrella term for application technique whose main goal is to degrade the accuracy of the retrieved disassembly so what do I mean by inaccurate disassembly then or an inaccurate disassembly contains it's basically a disassembly that contains code that will never be executed during program runtime and here's an example shown here the first instruction is basically an if statement and if this if statement evaluates to true it will the execution will go to where the arrow is
pointing so it will start executing the the add instruction and then the decrement instruction but if the if statement evaluates to false it will go to an instruction right after that the if statement which is the MOV move instruction but this particular if statement during runtime will actually always evaluate to false but that this assembler does not know that so it's still disassembled the code at where the arrow is pointing or the by edge where the arrow is pointing as Co instruction thus inaccurate disassembly so what is opaque predicates opaque predicates is basically just that there are conditional branches that always evaluate to true or false this means that one of the branch is always
unreachable at programming runtime so jump bytes or random data bytes that are not meant to be parses Co instruction can be inserted and in this particular paper case shown here which is kind of like in a CFG representation this particular opaque predicate contains a predicate that will always evaluates to true this means that you can put junk by at the false branch so other than either pro there are also other other tool that will try to automatically identify opaque predicates died including SEC and also a binary ninja plug-in copaque predicate patcher and the way they work is that at every basically if statement they will ask the question of can both branch be executed and if the answer is
no or if they can determine that the answer is no then they know that an opaque predicate exists but the problem with that approach is that opaque predicates well the predicate itself depending on how its constructed determining that property or being able to answer that question is non-trivial so since identifying opaque predicate is high idle Pro takes a heuristic based approach to identify them instead and here's Ida heuristic if Ida Pro detects overlap instruction and sibling basic block it will always assume that the conditional branch is an opaque predicate so what I mean by a sibling basic block or in the picture shown here basically plot a sorry x papi and base bossy are sibling because they originate
from the same if statement and what I mean by overlapping structure overlap instructions are wins one or more instruction bytes are interpreted as more than one instruction so for the opaque predicates here if the if statements - true then the by 31 C 0 D 1 CA will be paused as an XOR and our instruction but if it evaluates to false those sent 4 bytes will be evaluated as an move instruction so here's where either makes an incorrect assumption if it takes our structure I just discussed earlier basically overlap instruction and sibling basic block it will always assume that the jump bike is placed in the false branch but there's really no stopping for the junk by to place in the
true branch instead and that's look at a more concrete example here so and this disassembly the second instruction is basically basically the if statement and if the if statement evaluates to true it will go to the instruction and with the not jump label is so it will start executing the XOR and all our instruction and just to explain that this assembly a little bit those two instruction actual and all are essentially sets ei X - 0 and eix is the return return value so on a higher level this function will return 0 as shown by this disassembly but if we look at the false branch which is the instruction that follows the JN z or the if
statement essentially that instruction is not disassembled it's just left as the data by b8 so it's just left as a rata by why didn't I die disassemble that well I thought detect that structure we discussed earlier basically overlapping instruction and sibling basic block and no and remember once I detect that structure it will always assume that junk by 2 to be placed in the false branch so essentially what happens is that either the basically believed that be a gala by is a jump by and not an instruction pike but for example the junk bite is actually placed in the true branch instead so this means that the EXO and all our instruction will actually never
be executed they are lately all the junk bike and the real instruction actually starts there so the instruction should actually be paused at where the be a data bias and if we disassemble from there we see that what's really will be executed during program run time is that EAX register will be a sign non zero value so essentially instead of returning zero this function well I should return non zero value so remember how previously I said how this particular about this opaque bracket is stealthier well how's it out here well here we're able to achieve three things first we make either display the wrong structure the EXO and our second we make I doubt not
disassemble the authentic instruction and third we make I Donna show any sign of distress on that there's some problem going on with the disassembly so before either implemented this particular heuristic to detect opaque predicates if if there's overlap instruction I doubt we'll highlight certain part of the disassembly in red to let the user know what the analysts know that something is wrong but since here I'd I believed I had successfully detected opaque predicates the show it does not do that type of highlighting home so it shows zero sign of distress to the analysts so in summary really when trying to implement occupation try to respect each property that makes up this time-consuming aspect and right now
really the focus has only been on the potency and residence property but we should really also focus on the stealth property because it is also equally as important thank you I guess any question oh oh yeah the question was how does the earlier example look like on the photograph oh we're showing Ida actually to be honest I I don't remember but if Ida if I died to test any sorry second actually yeah it was show not the other branches that's why I will assume too because I don't believe that that's actually correct and correct this assembly so the control flow graph would just be it will just be policy one branch pointing to the other but I actually don't remember
so I can say that for sure so I need the questions
okay thanks just gonna open it up
excuse me just one more question for you you said there was opening predicate Hatcher's do they work when the predicate itself relies on two variables that are unknown or do you have to feed it known States for it to be able to determine that something is OPIC oh yeah so for that particular plugin actually by the binary ninja disassembler they they can't do this more events program analysis technique called value set analysis which is basically the ability to like for a register they will try to determine all the value in that register so for that particular plugin if it determines that the it's the wall that the register that the if statement depends on always evaluate to the same
value then it will it will basically no dice an opaque predicate but if we can't determine that then then it doesn't so let's just say if the construction of the predicate is still like because I know that and they actually talk about the limitation and so the limitation so basically how well that tool work is based on how well the value set analysis is so and certain limitation is basically if I remember correctly if the predicate depends on like is it may be may be memory like on the heap like they won't do certain analysis if the predicate is constructing a certain way so one more question if you uh you don't mind oh yeah for Ida if the junk jump
goes to a location that doesn't overlap with any other functions will I to pick up that that is a opaque predicate or do I have to overlap so yeah I does case it does have to overlap so I so in a way either heuristic is very it's it's very it's incomplete per se so it's an incomplete implementation to detect opaque predicates so ah thank you