예제 #1
0
    def getDependencies( self,  gadgetDep ):
        """
        getDependencies : Computes dependencies for this register, and store them into gadgetDep
                  Return the dependencies as a list of couples ( Expression, Condition )
        """
        # If dependency already calculated 
        if( gadgetDep.regDep.get(self.reg) != None ):
            return gadgetDep.regDep[self.reg]
                 
        # Else we build it :
        # If ind is 0 then we reached a leaf of the graph because it's the initial value of the register 
        if( self.reg.ind == 0 ):
            res = [[SSAExpr(self.reg), CTrue() ]]
            gadgetDep.regDep[self.reg] = res
            return res
        # Else we test if bad node 
        # -> this is an un-understandable but harmless bug, additionnal empty nodes are added to the graph 
        # don't know why they are created yet .... :/     
        if( len(self.outgoingArcs) == 0 and isinstance( self.expr, SSAExpr ) and self.reg == self.expr.reg):
            return []
        # Here we know there are dependencies to compute, so we continue to explore the graph
        
        # We take into account the potential previous conditional jmps 
        resCond = CurrentAnalysis.graph.condPath[self.jmpLvl]
        resExpr = self.expr
        # WARNING : we suppose that each node has only one or no arc towards MEM, not more !
        resPrec = [[self.expr, resCond]]
        # For each arc, we replace step by step the expressions 
        res = []
            
        for a in self.outgoingArcs:
            res = []
            # For each arc we get a list replacement value and the condition
            if( isinstance( a.dest, MEMNode )):
                dep = a.dest.getDependencies( a.num, a.label, a.size, gadgetDep )
            else:
                dep = a.dest.getDependencies( gadgetDep )
            for path in dep:
                if ( isinstance( a.dest, MEMNode )):
                    res += [[p[0].replaceMemAcc(a.label, path[0]), Cond(CT.AND, p[1],path[1])] for p in resPrec ]
                elif( isinstance( a.dest, ITENode )):
                    res += [[p[0].replaceITE(path[0]), Cond(CT.AND, p[1],path[1])] for p in resPrec ] 
                else:
                    res += [[p[0].replaceReg( a.dest.reg, path[0] ), Cond(CT.AND, p[1],path[1])] for p in resPrec ]
            resPrec = res
                
        if( len(res) == 0 ):
            res = [[self.expr, resCond]]
        
        # Taking into account the potential conditionnal jumps     
        # We add the case when the jump had not been taken 
        if( self.jmpLvl > 0 ):
            dep = CurrentAnalysis.graph.nodes[str(regBeforeLastJmp(self.reg, self.jmpLvl))].getDependencies( gadgetDep )
            for d in dep:
                res.append( [d[0], Cond(CT.AND, d[1], CurrentAnalysis.graph.condJmps[self.jmpLvl])]) 

        gadgetDep.regDep[self.reg] = res
            
        return res
예제 #2
0
 def lookUpEXPRtoREG(self, expr, n=10):
     """
     Return at most n gadgets that correspond to expr
     """
     i = 0
     found = 0
     res = []
     while (i < len(self.expr_list) and len(res) < n):
         cond = Cond(CT.EQUAL, self.expr_list[i], expr)
         if (cond.isTrue(hard=True)):
             res += self.gadget_list[i]
         i = i + 1
     return res
예제 #3
0
    def getDependencies(self, gadgetDep):
        resPrec = [[self.iftrue, self.cond]]
        # We first compute when the condition is TRUE :
        # For each arc, we replace step by step the expressions
        for a in self.outgoingArcs:
            resTrue = []
            # For each arc we get a list replacement value and the condition
            if (isinstance(a.dest, MEMNode)):
                dep = a.dest.getDependencies(a.num, a.label, a.size, gadgetDep)
            else:
                dep = a.dest.getDependencies(gadgetDep)
            for path in dep:
                if (isinstance(a.dest, MEMNode)):
                    resTrue += [[
                        p[0].replaceMemAcc(a.label, path[0]),
                        Cond(CT.AND, p[1], path[1])
                    ] for p in resPrec]
                else:
                    resTrue += [[
                        p[0].replaceReg(a.dest.reg, path[0]),
                        Cond(CT.AND, p[1], path[1])
                    ] for p in resPrec]
            resPrec = resTrue

        res = resPrec
        resPrec = [[self.iffalse, self.cond.invert()]]
        # Then the case when the condition is FALSE
        # For each arc, we replace step by step the expressions
        for a in self.outgoingArcsCond:
            resFalse = []
            # For each arc we get a list replacement value and the condition
            if (isinstance(a.dest, MEMNode)):
                dep = a.dest.getDependencies(a.num, a.label, a.size, gadgetDep)
            else:
                dep = a.dest.getDependencies(gadgetDep)
            for path in dep:
                if (isinstance(a.dest, MEMNode)):
                    resFalse += [[
                        p[0].replaceMemAcc(a.label, path[0]),
                        Cond(CT.AND, p[1], path[1])
                    ] for p in resPrec]
                else:
                    resFalse += [[
                        p[0].replaceReg(a.dest.reg, path[0]),
                        Cond(CT.AND, p[1], path[1])
                    ] for p in resPrec]
            resPrec = resFalse
        res = res + resPrec
        return res
예제 #4
0
 def lookUpCSTtoMEM(self, addr, cst, n=10):
     """
     Returns gadgets numbers that put cst at mem(addr) as a list of gadgets uids
     cst - (int)
     addr - Expr
     """
     i = 0
     found = 0
     res = []
     # Iterate for all write addresses
     while (i < len(self.addr_list) and len(res) < n):
         # If we have a dependencie for the requested constant
         if (cst in self.written_values[i]):
             # Comparing the addresses with hard=True so we call z3 solver
             cond = Cond(CT.EQUAL, self.addr_list[i], addr)
             if (cond.isTrue(hard=True)):
                 res += self.written_values[i][cst]
         i = i + 1
     return res
예제 #5
0
    def flattenITE(self):

        newArgs = [a[0].flattenITE() for a in self.args]
        listArgs = [[[], CTrue()]]
        tmp = []
        for listA in newArgs:
            for a in listA:
                for arg in listArgs:
                    tmp.append(arg[0] + [a[0]], Cond(CT.AND, arg[1], a[1]))
                listArgs = tmp
        # listArgs contains now an array of couples ( list, condition )
        res = [[Cat(a[0]), a[1]] for a in listArgs]
        return res
예제 #6
0
 def flattenITE(self):
     """
     !!! Works only for unary or binary operations 
     """
     res = []
     if (len(self.args) == 2):
         flatLeft = self.args[0].flattenITE()
         flatRight = self.args[1].flattenITE()
         for f in flatLeft:
             for f2 in flatRight:
                 res.append([
                     Op(self.op, [f[0], f2[0]]),
                     Cond(CT.AND, f[1], f2[1])
                 ])
         return res
     elif (len(self.args) == 1):
         flat = self.args[0].flattenITE()
         return [[Op(self.op, self.size, f[0]), f[1]] for f in flat]
     else:
         raise ExprException(
             " flattenITE can not be used with an operator on more than 2 arguments (%d here) "
             % len(self.args))
예제 #7
0
    def getMemDependencies( self, gadgetDep ):
        """
        Extract dependencies from memory
        Dependencies of the memory are returned in the form of a dictionnary of lists of couples
            - Dictionnary entries are addresses where the memory is accessed ( like R7_0 + R6_0 + 0x56 ) 
            - Dictionnary values are lists that are classical dependencies. This means lists of couples [value, condition] 
            
        Parameters:
            (gadgetDep) (GadgetDependencies) The structure where to store the memory dependencies 
        """
    
        #raise GraphException("Function getMemDependencies() not yet implemented, sorry !")
        
        # The three dictionnaries below MUST have the exact same keys 
        res = dict() # Key: Expr (address of store), Value: list of dependencies 
        previousStoreSizes = dict() # Key: Expr (address of store), Value: size of the store   
        

        tmpCond = None
        # We go through memory-writes in chronological order 
        for a in sorted(self.outgoingArcs):
            # Key to manipulate the current store address 
            addrKey = str(simplify(a.label.toZ3()))
            # We get the dependency for the node that is written in memory 
            dep = a.dest.getDependencies(gadgetDep)
            # !!! HERE WE DON'T NEED TO CORRECT THE DEPENDENCIES WITH THE self.storedValues BECAUSE IT HAS ALREADY BEEN DONE FOR REGISTERS AND WE USE THEIR FINAL DEPENDENCIES DIRECTLY 
            if( isinstance(a.dest, SSANode)):
                dep = [[self.storedValues[a.num].replaceReg(a.dest.reg, d[0]), d[1]] for d in dep ]    
            
            # Handling conditionnal jumps 
            if( tmpCond is None ):
                # If first memory access, then we get the condPath for the adequate level (condition that must be true so that we haven't jumper out from the gadget) 
                tmpCond = CurrentAnalysis.graph.condPath[a.jmpLvl]
            else:
                # Else we only add the condJump corresponding to this level 
                tmpCond = Cond( CT.AND, tmpCond, CurrentAnalysis.graph.condJmps[a.jmpLvl].invert() )
            storeLen = a.size / 8 # Number of bytes written by this arc
            previousStoreSizes[a.label] = storeLen
            #readDict = {addrKey:0} # Basic constraint for optimisation 
            
            # Create a new dependency for this 
            
            # Updating dependencies for the previous memory-store
            resTmp = dict()
            for writeAddr, prevDep in res.iteritems():
                # 1st Case Preparation : New store doesn't affect old store
                # Get the size of the previous by looking at one dependency (little hack and not so clean but heh)
                previousStoreSize = previousStoreSizes[writeAddr] 
                higher = Op( "Add", [writeAddr, ConstExpr(previousStoreSize, writeAddr.size)] ) 
                lower = Op( "Sub", [writeAddr, ConstExpr( a.size, writeAddr.size )]) 
                outCond = Cond( CT.OR, Cond( CT.GE, a.label, higher ), Cond( CT.LE, a.label, lower ))
                newDict = {addrKey:[1-storeLen, previousStoreSize-1]}
                
                newDep = []
                # Update each old dependency 
                for prev in prevDep:
                    # 1st Case Still...
                    if( self.compatibleAccesses( prev[2], newDict )):
                        newDep.append( [prev[0], Cond( CT.AND, outCond, prev[1]), self.dictFusion(newDict, prev[2])]) 
                
                    # Now 2d Case: New store overwrites old store  
                    # ...
                    # Offset = current store - previous store 
                    for offset in range(1-storeLen, previousStoreSize-1):
                        newDict = {addrKey:offset}
                        newStorePossibleValue = Op("Add", [writeAddr, ConstExpr(offset, writeAddr.size)] )
                        addrCond = Cond( CT.EQUAL, a.label, newStorePossibleValue )
                        if( self.compatibleAccesses( newDict, prev[2] ) and self.filterOffset( offset, previousStoreSize, storeLen )):
                            # For each dep of the new store, we update with the case where it overwrites the previous stores 
                            for d in dep:
                                newValue = self.overWrite( offset, d[0], prev[0] )
                                newCond = Cond( CT.AND, Cond(CT.AND, prev[1], addrCond ), d[1] )
                                newDep.append( [newValue, newCond, self.dictFusion(newDict, prev[2])])
                                
                
                
                
                
                resTmp[writeAddr] = newDep
                
            # New dependency:
            resTmp[a.label] = []
            newStoreDict={addrKey:0}
            for d in dep:
                resTmp[a.label].append([d[0], d[1], newStoreDict])
            
            # Save everything 
            res = resTmp
            # ... 
            
        # Clean the deps from dictionnaries 
        for addr, dep in res.iteritems():
            dep = [[].append([d[0], d[1]]) for d in dep ]
        
        # Replace the memory addresses of the stores by their basic dependencies
        # So far we have MEM[expr] where expr doesn't necessarily have basic dependencies, so we want to express everything with the basic dependencies 
        
        gadgetDep.memDep = res
예제 #8
0
 def getDependencies( self, num, addr, size, gadgetDep ):
     """
     Extract dependencies from memory
     Parameters:
         (num) (int) The number of the arc in the graph that represents the load operation 
         (addr) (Expr) The address at which memory is read 
         (size) (int) The size in bits of the read
         (gadgetDep) (GadgetDependencies) The structure used to compute dependencies 
     """
     res = []
     tmp = num
     readLen = size / 8 
     addrID = -1 # Used to optimise combinations without calling the solver...
     addrKey = str(simplify(addr.toZ3()))
     readDict = {addrKey:0} # Basic constraint for optimisation 
     value = MEMExpr( addr, size )
     resTmp = [[MEMExpr(addr, size), CTrue(), readDict]]
     tmpCond = None
     # For each outgoing arc, i.e for each memory write  
     for a in sorted( self.outgoingArcs, reverse=False):
         optWriteKey = str(simplify(a.label.toZ3())) # key for the store address for optimisation 
         # If a.num > num, then we have checked all memory writes before the read we compute dependencies for 
         if( a.num >= num ):
             break
         # Get the dependencies for the register written in memory 
         dep = a.dest.getDependencies( gadgetDep )
         # We correct the dependencies in case we stored an expression and not only a register or constant 
         if( isinstance(a.dest, SSANode)):
             dep = [[self.storedValues[a.num].replaceReg(a.dest.reg, d[0]), d[1]] for d in dep ]    
         
         
         # Handle previous conditional jumps 
         if( tmpCond is None ):
             # If first memory access, then we get the condPath for the adequate level (condition that must be true so that we haven't jumper out from the gadget) 
             tmpCond = CurrentAnalysis.graph.condPath[a.jmpLvl]
         else:
             # Else we only add the condJump corresponding to this level 
             tmpCond = Cond( CT.AND, tmpCond, CurrentAnalysis.graph.condJmps[a.jmpLvl].invert() )
         storeLen = a.size / 8 # Number of bytes written by this arc 
         # For each dependency, we update the resTmp into some new array of dependencies 
         # This models a store operation overwriting previous memory contents 
         newResTmp = []
         # For each case, update possibilities 
         for prev in resTmp:
             # For each dependency of the register written in memory 
             for d in dep:
                 # We consider every possibility of memory overwrite ( offset between the read and write ). Some could modify 1 byte, others 2 bytes, etc... 
                 for offset in range( 1-storeLen, readLen-1  ):
                     writeAddr = Op( "Add", [addr, ConstExpr( offset, addr.size )])
                     newDict = {optWriteKey:offset}
                     if( self.compatibleAccesses( prev[2], newDict ) and self.filterOffset( offset, storeLen, readLen )):
                         newValue = self.overWrite( offset, d[0], prev[0] )
                         addrCond = Cond( CT.EQUAL, a.label, writeAddr )
                         newCond = Cond( CT.AND, Cond(CT.AND, prev[1], addrCond ), d[1] )
                         newResTmp.append( [newValue, newCond, self.dictFusion(newDict, prev[2])])
         # We keep the previous ones if the store is made out of the bounds of the read 
         higher = Op( "Add", [addr, ConstExpr(readLen, addr.size)] )
         lower = Op( "Sub", [addr, ConstExpr( storeLen, addr.size )])
         outCond = Cond( CT.OR, Cond( CT.GE, a.label, higher ), Cond( CT.LE, a.label, lower ))
         newDict = {optWriteKey:[1-storeLen, readLen-1]}
         for prev in resTmp:
             if( self.compatibleAccesses( prev[2], newDict )):
                 newResTmp.append( [prev[0], Cond( CT.AND, outCond, prev[1]), self.dictFusion(newDict, prev[2])] )
         # give resTmp its new value 
         resTmp = newResTmp
     # Extract only the values and conditions 
     res = [[d[0], d[1]] for d in resTmp]
     
     return res
예제 #9
0
    def simplifyDependencies( self ):
        """
        Simplifies basic operations, conditions... in order to have only basic dependencies 
        A 'basic' dependency is an expression in which SSA Registers have only null indexes ( R?_0 )
        """    
        
        # (1) First compute basic dependencies for registers 
        
        # replaceTable stores the registers that could be replaced by a basic dependency 
        replaceTable = {}
        
        
        
        # For each register get the best basic dep we have
        for reg in CurrentAnalysis.graph.getRegisters():
            # if only one dependency, i.e no other possibility of end-value 
            if( self.regDep.get(reg) != None and len(self.regDep[reg]) == 1 ):
                replaceTable[reg] = self.regDep[reg][0][0]
                self.regDep[reg][0][1] = CTrue()
                
        # Repeated procedure until no register with index > 0 is found 
        stop = False
        while( not stop):
            stop = True
            # I know... the code below is very nasty
            # ---> should at least rename variables 
            # For each register 'reg' we simplifify its dependencies   
            for reg in self.regDep.keys():
                # At the end of the loop, 'newDeps' shall be new dependencies of register 'reg' 
                newDeps = []
                # For each dependency 'dep' of 'reg'
                for dep in self.regDep[reg]:
                    # At the end of the loop, 'newDepDeps' shall be the dependency 'dep' simplified in one or many dependencies 
                    newDepDeps = [[dep[0], dep[1]]] # Here newDepdeps <=> [dep]
                    # We start by simplifying the value
                    # For each register in the expression 
                    for register in dep[0].getRegisters():
                        if( register.ind > 0 ):
                            stop = False
                            # We replace it by its own dependencies 
                            # If 'register' has only one dependency -> direct replacement 
                            if( replaceTable.get(register) != None ):
                                newDepDeps[0][0] = dep[0].replaceReg( register, replaceTable[register] )
                            # Else we go through them and make the replacement 
                            else:
                                tmpDep = []
                                for depdep in self.regDep[register]:
                                    for newDepDep in newDepDeps:
                                        depVal = newDepDep[0].replaceReg( register, depdep[0] )
                                        depCond = Cond( CT.AND, newDepDep[1], depdep[1])
                                        tmpDep.append( [depVal, depCond])
                                newDepDeps = tmpDep    
                    # Then same thing for the condition
                    # !! The only condition of the dependency 'dep' can now have been transformed into several ones depdending on the previous simplification of the value, into list newDepDeps
                    # So we iterate into 'dep' transformed into a list of dependencies 'gDep' ( Generated DEPendencies )
                    newResTruc = []
                    for gDep in newDepDeps:
                        newDepDepsF = [[gDep[0], gDep[1]]]
                        # Same operation than before 
                        for register in gDep[1].getRegisters():
                            if( register.ind > 0 ):
                                stop = False
                                if( replaceTable.get(register) != None ):
                                    newDepDepsF[0][1] = gDep[1].replaceReg( register, replaceTable[register])
                                else:
                                    tmpDep = []
                                    for depdep in self.regDep[register]:
                                        for newDepDep in newDepDepsF:
                                            depVal = newDepDep[0]
                                            depCond = Cond( CT.AND, newDepDep[1].replaceReg(register,depdep[0]) , depdep[1])
                                            tmpDep.append( [depVal, depCond] )
                                    newDepDepsF = tmpDep
                        newResTruc += newDepDepsF
                    newDepDepsF = newResTruc
                            
                    # Adding the simplified 'dep' in the dependency list of 'reg' 
                    newDeps += newDepDepsF
                # The new dependencies of 'reg' are 'newDeps' ;-) 
                self.regDep[reg] = newDeps
        
        # (2) Then basic dependencies for the memory 
        
        for addr, deps in self.memDep.iteritems():
            newMemDep = dict()
            newDepsForAddr = []
            # Compute the basic dependency for the dependency list 
            # First for registers 
            for val, cond in deps:
                # Replace all registers in the value field
                # To get a new list of (val, cond)
                newDepsForVal = [[val, cond]]
                # For each register, we replace in all dependencies 
                for reg in val.getRegisters():
                    # Replace by all the possible values for this register 
                    for regdep in self.regDep[reg]:
                        tmpNewDepsForVal = []
                        # Update the temporary results 
                        for tmpDep in newDepsForVal:
                            tmpNewDepsForVal.append([tmpDep[0].replaceReg( reg, regdep[0] ), Cond(CT.AND, regdep[1], tmpDep[1])])
                        newDepsForVal = tmpNewDepsForVal

                # Replace all registers in condition fields
                newDepsForCond = newDepsForVal
                for reg in cond.getRegisters():
                    for regdep in self.regDep[reg]:
                        tmpNewDepsForCond = []
                        # Update the temporary results
                        for tmpDep in newDepsForCond:
                            tmpNewDepsForCond.append( [tmpDep[0], Cond(CT.AND, regdep[1], tmpDep[1].replaceReg(reg, regdep[0]))])
                        newDepsForCond = tmpNewDepsForCond
                    
                # Update the list of dependencies (now basic) for addr
                newDepsForAddr += newDepsForCond
                
            # Compute the basic dependencies for the memory address addr
            addrDeps = [[addr, CTrue()]]
            for reg in addr.getRegisters():
                for regdep in self.regDep[reg]:
                    tmpAddrDeps = []
                    for tmpDep in addrDeps:
                        tmpAddrDeps.append([tmpDep[0].replaceReg(reg, regdep[0]), Cond(CT.AND, tmpDep[1], regdep[1]) ])
                    addrDeps = tmpAddrDeps
                    
            # TODO : SIMPLIFY EXPRESSIONS HERE, OR IN THE BEGGINIG OF THE FUNCTION ??? 
            # Now combine the addrDeps and the newDepsForAddr in the final result for the gadget
            for newAddrDep in addrDeps:
                updateNewAddrDeps = []
                for dep in newDepsForAddr:
                    updateNewAddrDeps.append([dep[0], Cond(CT.AND, dep[1], newAddrDep[1])])
                newAddr = newAddrDep[0].simplify()
                newMemDep[newAddr] = updateNewAddrDeps
            self.memDep = newMemDep
            
            
            
        # Remove the dependencies for intermediate registers ( we don't care about R1_1 anymore if we have R1_3 in the end :/ )
        for reg in self.regDep.keys():
            if( reg.ind < CurrentAnalysis.gadget.regCount[reg.num]):
                del self.regDep[reg]
        
        # Cleaning and simplifying  
        for reg in self.regDep.keys():
            for dep in self.regDep[reg]:
                dep[0] = dep[0].simplify()
                dep[1].clean()
        for addr, deps in self.memDep.iteritems():
            for dep in deps:
                dep[0] = dep[0].simplify()
                dep[1].clean()
예제 #10
0
    def buildGraph(self, irsb):
        # (1) Initialisations...
        self.valuesTable = {}  # Keys are whatever, Values are Expr
        self.graph = Graph()  # Empty graph
        CurrentAnalysis.gadget = self
        CurrentAnalysis.graph = self.graph
        self.regCount = {}
        # Update the index counts and nodes for registers that already have a translation into generic IR
        for reg in Analysis.regNamesTable.values():
            self.regCount[reg] = 0
            node = SSANode(SSAReg(reg, 0), SSAExpr(SSAReg(reg, 0)))
            self.graph.nodes["R%d_0" % reg] = node
        self.graph.nodes["MEM"] = MEMNode()
        memAccCount = 0  # Hold the number of the next arc incoming/outgoing to/from the memory node

        # (2) Graph construction...
        # Iterate through all reill instructions :
        for i in range(0, len(irsb)):
            instr = irsb[i]
            self.nbInstr = self.nbInstr + 1
            # Translating different types of instructions
            if (instr.mnemonic == ReilMnemonic.NOP):
                pass
            # Basic operations ( ADD, SUB, MUL, etc )
            elif (isCalculationInstr(instr.mnemonic)):
                if (instr.operands[2]._name[0] == "t"):
                    expr = self.barfCalculationToExpr(instr.mnemonic,
                                                      instr.operands[0],
                                                      instr.operands[1],
                                                      instr.operands[2].size)
                    self.valuesTable[instr.operands[2]._name] = expr
                else:
                    expr = self.barfCalculationToExpr(instr.mnemonic,
                                                      instr.operands[0],
                                                      instr.operands[1],
                                                      instr.operands[2].size)
                    regExpr = self._getReg(instr.operands[2]._name)
                    reg = regExpr.reg
                    expr = self.translateFullRegAssignement(
                        expr, instr.operands[2])
                    reg = SSAReg(reg.num, reg.ind + 1)
                    self.valuesTable[str(reg)] = expr
                    # Adding the node
                    node = SSANode(reg, expr)
                    # Adding arcs toward other nodes and memory
                    for dep in expr.getRegisters():
                        # Dep is a SSAReg on which node depends
                        node.outgoingArcs.append(
                            Arc(self.graph.nodes[str(dep)]))
                    for mem in expr.getMemAcc():
                        addr = mem[0]
                        size = mem[1]
                        node.outgoingArcs.append(
                            Arc(self.graph.nodes["MEM"], memAccCount, addr,
                                size))
                        memAccCount += 1
                    self.graph.nodes[str(reg)] = node
                    self.regCount[reg.num] += 1

            # Memory load instruction
            elif (isLoadInstr(instr.mnemonic)):
                expr = self.barfLoadToExpr(instr.operands[0],
                                           instr.operands[2])
                if (instr.operands[2]._name[0] == "t"):
                    self.valuesTable[instr.operands[2]._name] = expr
                else:
                    regExpr = self._getReg(instr.operands[2]._name)
                    reg = regExpr.reg
                    expr = self.translateFullRegAssignement(
                        expr, instr.operands[2])
                    reg.ind += 1
                    self.regCount[reg.num] += 1
                    self.valuesTable[str(reg)] = expr
                    # Adding node towards memory
                    node = SSANode(reg, expr)
                    for mem in expr.getMemAcc():
                        addr = mem[0]
                        size = mem[1]
                        node.outgoingArcs.append(
                            Arc(self.graph.nodes["MEM"], memAccCount, addr,
                                size))
                        memAccCount += 1
                    self.graph.nodes[str(reg)] = node

            # Memory store instruction
            elif (isStoreInstr(instr.mnemonic)):
                expr = self.barfOperandToExpr(instr.operands[0])
                addr = self.barfOperandToExpr(instr.operands[2])
                #if( isinstance( instr.operands[0], ReilImmediateOperand )):
                #node = ConstNode( instr.operands[0].immediate, instr.operands[0].size )
                #self.graph.nodes["MEM"].outgoingArcs.append( Arc( node, memAccCount, addr, expr.size ))
                if (isinstance(expr, ConstExpr)):
                    node = ConstNode(expr.value, expr.size)
                    self.graph.nodes["MEM"].outgoingArcs.append(
                        Arc(node, memAccCount, addr, expr.size))
                elif (not expr.getRegisters()):
                    raise GadgetException(
                        "Expression is neither ConstExpr nor has registers and should be written in memory ? - not yet supported!"
                    )
                else:
                    self.graph.nodes["MEM"].outgoingArcs.append(
                        Arc(self.graph.nodes[str(expr.getRegisters()[0])],
                            memAccCount, addr, expr.size))
                self.graph.nodes["MEM"].storedValues[memAccCount] = expr
                memAccCount += 1

            # Transfer value into register
            elif (isPutInstr(instr.mnemonic)):
                if (instr.operands[2]._name[0] == "t"):
                    expr = self.barfOperandToExpr(instr.operands[0])
                    if (instr.operands[2].size != expr.size):
                        expr = Convert(instr.operands[2].size, expr)
                    self.valuesTable[instr.operands[2]._name] = expr
                else:
                    regExpr = self._getReg(instr.operands[2]._name)
                    reg = regExpr.reg
                    expr = self.barfOperandToExpr(instr.operands[0])
                    if (instr.operands[0].size < instr.operands[2].size):
                        expr = self.translateFullRegAssignement(
                            expr, instr.operands[2])
                    else:
                        expr = Convert(instr.operands[2].size, expr)
                    if (instr.operands[2].size != REGSIZE.size):
                        expr = self.translateFullRegAssignement(
                            expr, instr.operands[2])
                    regDep = expr.getRegisters()
                    memDep = expr.getMemAcc()

                    # Adding node and arcs to the graph
                    reg = SSAReg(reg.num, reg.ind + 1)
                    node = SSANode(reg, expr)
                    for r in regDep:
                        node.outgoingArcs.append(Arc(self.graph.nodes[str(r)]))
                    for mem in memDep:
                        addr = mem[0]
                        size = mem[1]
                        node.outgoingArcs.append(
                            Arc(self.graph.nodes["MEM"], memAccCount, addr,
                                size))
                        memAccCount += 1
                    self.graph.nodes[str(reg)] = node
                    self.regCount[reg.num] += 1
                    self.valuesTable[str(reg)] = expr

            # Boolean IS Zero instrution
            # BISZ( a, b ) has the following effects :
            #    b <- 1 if a == 0
            #    b <- 0 if a != 0
            elif (instr.mnemonic == ReilMnemonic.BISZ):
                zero = ConstExpr(0, instr.operands[0].size)
                ifzero = ConstExpr(1, instr.operands[2].size)
                ifnotzero = ConstExpr(0, instr.operands[2].size)
                testedValue = self.barfOperandToExpr(instr.operands[0])
                # If operands[0] == 0 then the value assigned to operands[2] is 1.
                # If operands[0] != 0 then operands[2] becomes 0
                cond = Cond(CT.EQUAL, testedValue, zero)
                expr = ITE(cond, ifzero, ifnotzero)
                if (instr.operands[2]._name[0] == "t"):
                    self.valuesTable[instr.operands[2]._name] = expr
                else:
                    regExpr = self._getReg(instr.operands[2]._name)
                    reg = regExpr.reg
                    reg.ind += 1
                    self.regCount[reg.num] += 1
                    self.valuesTable[str(reg)] = expr
                    # Adding node to the graph
                    # Creation of the ite node
                    iteNode = ITENode(cond, ifzero, ifnotzero)
                    # Link the real node to the ITE node
                    node = SSANode(reg, Convert(REGSIZE.size, expr))
                    node.outgoingArcs.append(Arc(iteNode))
                    self.graph.nodes[str(reg)] = node

            # Conditionnal jump
            elif (instr.mnemonic == ReilMnemonic.JCC):
                # Determine the address where to jmp
                # If jmp to a fixed location
                if (isinstance(instr.operands[2], ReilImmediateOperand)
                        and instr.operands[2].size != 40
                        and instr.operands[2].size != 72):
                    addr = ConstExpr(instr.operands[2].immediate)
                    addr.size = REGSIZE.size
                # If it is a pointer
                elif (instr.operands[2].size == 40
                      or instr.operands[2].size == 72):
                    #We test if the value is less than 0x100
                    # If yes, then we ignore the condition because unable to compute dependencies
                    # This kind of small values depict an instruction simulated in many basic blocks
                    # We do not handle conditions for the Instr Pointer INSIDE a gadget
                    if (isinstance(instr.operands[2], ReilImmediateOperand) and
                        (instr.operands[2].immediate >> 8) - self.addr < 0x1):
                        raise GadgetException(
                            "REIL instruction(s) too complicated to emulate in gadget:\n"
                            + self.asmStr)
                    # We also test if there is a jump inside the bounds of the gadget
                    # For now those are also not supported
                    # Sadly, this also suppresses some conditional conditions
                    if (isinstance(instr.operands[2], ReilImmediateOperand) and
                        (instr.operands[2].immediate >> 8) - self.addr <
                        (len(self.hexStr) / 4)):

                        raise GadgetException(
                            "Jumps inside the gadget are not handled yet in gadget:\n"
                            + self.asmStr)
                    # Get the real return/jump address with an 8 bit SHR
                    expr = self.barfOperandToExpr(instr.operands[2])
                    addr = Extr(expr.size - 1, 8, expr)
                else:
                    addr = self.barfOperandToExpr(instr.operands[2])
                ip = self._getReg(
                    Analysis.ArchInfo.ip).reg  # Get the instruction pointer
                ip.ind += 1
                # Quick check if simple 'ret' so the expression is easier to read
                # A jump is always taken if first argument is a constant != 0
                if (isinstance(instr.operands[0], ReilImmediateOperand)
                        and instr.operands[0].immediate != 0):
                    self.valuesTable[str(ip)] = addr
                    expr = addr
                    node = SSANode(ip, Convert(REGSIZE.size, addr))
                    for dep in addr.getRegisters(ignoreMemAcc=True):
                        node.outgoingArcs.append(
                            Arc(self.graph.nodes[str(dep)]))
                    for mem in addr.getMemAcc():
                        address = mem[0]
                        size = mem[1]
                        node.outgoingArcs.append(
                            Arc(self.graph.nodes["MEM"], memAccCount, address,
                                size))
                        memAccCount += 1
                    self.regCount[ip.num] += 1
                    self.graph.nodes[str(ip)] = node
                # Else processing conditional jump
                else:
                    # Create node and stuff
                    reg = ip
                    zero = ConstExpr(0, instr.operands[0].size)
                    cond = Cond(CT.NOTEQUAL,
                                self.barfOperandToExpr(instr.operands[0]),
                                zero)
                    # Update the info about conditional jumps in Graph.py module
                    self.graph.condJmps.append(cond)
                    self.graph.condPath.append(
                        Cond(CT.AND, cond.invert(),
                             self.graph.condPath[self.graph.countCondJmps]))
                    # TODO : this seems not to put the good address into nextInstrAddr ???
                    nextInstrAddr = ConstExpr(irsb[i + 1].address >> 8,
                                              REGSIZE.size)
                    # 1 - FIRST STEP : ITE Node to say : IP takes new value OR stays the same
                    expr = ITE(cond, addr,
                               ConstExpr(instr.address >> 8, REGSIZE.size))
                    self.valuesTable[str(reg)] = expr
                    # Adding node to the graph
                    # Creation of the ite node
                    # We consider that either the jump is taken ( to addr )
                    #   or the value stays the one of the current instruction ( instr.address >> 8 )
                    iteNode = ITENode(
                        cond, addr, ConstExpr(instr.address >> 8,
                                              REGSIZE.size))
                    for dep in addr.getRegisters():
                        iteNode.outgoingArcs.append(
                            Arc(self.graph.nodes[str(dep)]))
                    for mem in addr.getMemAcc():
                        address = mem[0]
                        size = mem[1]
                        iteNode.outgoingArcs.append(
                            Arc(self.graph.nodes["MEM"], memAccCount, address,
                                size))
                        memAccCount += 1
                    #iteNode.outgoingArcsCond.append( Arc( self.graph.nodes[str(prevOcc(reg))], -1, None))
                    # Link the real node to the ITE node
                    node = SSANode(reg, expr)
                    node.outgoingArcs.append(Arc(iteNode))
                    self.graph.nodes[str(reg)] = node
                    # And do not forget
                    self.regCount[reg.num] += 1
                    self.graph.countCondJmps += 1
                    # 2 - SECOND STEP
                    # We update the register again with the address of the next instruction
                    reg = SSAReg(reg.num, reg.ind + 1)
                    node = SSANode(reg, nextInstrAddr)
                    self.graph.nodes[str(reg)] = node
                    self.regCount[reg.num] += 1
            else:
                raise GadgetException(
                    "REIL operation <%s>  not supported in gadget:\n%s" %
                    (ReilMnemonic.to_string(instr.mnemonic), self.asmStr))