示例#1
0
 def __init__(self, addr_list, raw):
     """
     addr_list = list of addresses of the gadget (if duplicate gadgets)
     raw = raw string of gadget asm 
     """
     # Check the type of the gadget 
     # Check for 'int 0x80' gadgets
     if( raw == '\xcd\x80' and Arch.currentIsIntel()): 
         self.type = GadgetType.INT80
         self.asmStr = 'int 0x80'
         self.hexStr = '\\xcd\\x80'
         self.addrList = addr_list
         self.nbInstr = self.nbInstrREIL = 1
         self.semantics = Semantics() 
         return 
     # Check for 'syscall' gadgets 
     elif( raw == '\x0f\x05' and Arch.currentIsIntel()):
         self.type = GadgetType.SYSCALL
         self.asmStr = 'syscall'
         self.hexStr = '\\x0f\\x05'
         self.addrList = addr_list
         self.nbInstr = self.nbInstrREIL = 1
         self.semantics = Semantics()
         return 
     
     # Translate raw assembly into REIL 
     # Then compute the Graph and its semantics 
     try:
         (irsb, ins) = Arch.currentArch.asmToREIL(raw)
     except Arch.ArchException as e:
         raise GadgetException(str(e))
     try: 
         self.graph = REILtoGraph(irsb)
         self.semantics = self.graph.getSemantics()
     except GraphException as e:
         raise GadgetException("(In {}) - ".format('; '.join(str(i) for i in ins)) + str(e))
     
     self.type = GadgetType.REGULAR
     # Possible addresses     
     self.addrList = addr_list
     # String representations
     self.asmStr = '; '.join(str(i) for i in ins) 
     self.hexStr = '\\x' + '\\x'.join("{:02x}".format(ord(c)) for c in raw)
     # Length of the gadget 
     self.nbInstr = len(ins)
     self.nbInstrREIL = len(irsb)
     
     # List of modified registers 
     # And of memory-read accesses 
     self._modifiedRegs = []
     self._memoryReads = []
     for reg_num in list(set([reg.num for reg in self.semantics.registers.keys()])):
         # Check if there is an empty semantics 
         if( not self.getSemantics(reg_num)):
             #self.semantics.registers.pop(reg)
             log("Gadget ({}) : empty semantics for {}"\
             .format(self.asmStr, Arch.r2n(reg_num)))
             self._modifiedRegs.append(reg_num)
             continue
         # Get modified reg
         if ((SSAExpr(reg_num,0) != self.getSemantics(reg_num)[0].expr) ):
             self._modifiedRegs.append(reg_num)
         # Get memory reads 
         for pair in self.getSemantics(reg_num):
             self._memoryReads += [m[0] for m in pair.expr.getMemAcc()]
               
     self._modifiedRegs = list(set(self._modifiedRegs))
     
     # SP Increment 
     if( self.type != GadgetType.REGULAR ):
         self.spInc = None
     else:
         sp_num = Arch.spNum()
         if( not sp_num in self.graph.lastMod ):
             self.spInc = 0
         else:                
             sp = SSAReg(sp_num, self.graph.lastMod[sp_num])
             if( len(self.semantics.get(sp)) == 1 ):
                 (isInc, inc) = self.semantics.get(sp)[0].expr.isRegIncrement(sp_num)
                 if( isInc ):
                     self.spInc = inc
                 else:
                     self.spInc = None
             else:
                 self.spInc = None
     
     # Return type
     self.retType = RetType.UNKNOWN
     self.retValue = None
     if( self.type == GadgetType.REGULAR ):
         ip_num = Arch.n2r(Arch.currentArch.ip)
         ip = SSAReg(ip_num, self.graph.lastMod[ip_num])
         sp_num = Arch.n2r(Arch.currentArch.sp)
         
         if( self.spInc != None ):
             for p in self.semantics.get(ip):
                 if( p.cond.isTrue()):
                     if( isinstance(p.expr, MEMExpr)):
                         addr = p.expr.addr
                         (isInc, inc) = addr.isRegIncrement(sp_num)    
                         # Normal ret if the final value of the IP is value that was in memory before the last modification of SP ( i.e final_IP = MEM[final_sp - size_of_a_register )        
                         if( isInc and inc == (self.spInc - (Arch.currentArch.octets)) ):
                             self.retType = RetType.RET
                             self.retValue = p.expr
                     elif( isinstance(p.expr, SSAExpr )):
                         self.retValue = p.expr
                         # Try to detect gadgets ending by 'call' 
                         if( ins[-1]._mnemonic[:4] == "call"):
                             self.retType = RetType.CALL
                         else:
                             self.retType = RetType.JMP
示例#2
0
 def __init__(self, msg):
     self.msg = msg 
     log(msg)
示例#3
0
def build(pair_list):
    """
    Takes a list of pairs (addr, raw_asm) corresponding to 
    gagets (their address and their intructions as a byte string)
    Fills the 'gadgets' and 'db' global structures ;) 
    """
    def sigint_handler(signal, frame):
        global sigint
        sigint = True

    def timeout_handler(signum, frame):
        global sigalarm
        sigalarm = True
        signal.alarm(0)
        raise TimeOutException('Timeout')

    global gadgets, db, sigint
    gadgets = []
    raw_to_gadget = dict()
    sigint = False
    original_sigint_handler = signal.getsignal(signal.SIGINT)
    signal.signal(signal.SIGINT, sigint_handler)
    signal.signal(signal.SIGALRM, timeout_handler)

    info(string_bold("Creating gadget database\n"))
    startTime = datetime.now()
    success = i = 0
    # Create the gadgets list
    for (addr, raw) in pair_list:
        charging_bar(len(pair_list) - 1, i, 30)
        if (sigint):
            break
        if (raw in raw_to_gadget):
            gadgets[raw_to_gadget[raw]].addrList.append(addr)
            success += 1
        else:
            try:
                signal.alarm(1)
                gadget = Gadget([addr], raw)
                signal.alarm(0)
                success += 1
                gadgets.append(gadget)
                raw_to_gadget[raw] = len(gadgets) - 1
            except (GadgetException, TimeOutException) as e:
                signal.alarm(0)
                if (isinstance(e, GadgetException)):
                    log("Gadget ({}) :  ".format('\\x'+'\\x'\
                    .join("{:02x}".format(ord(c)) for c in raw)) + str(e))
        i += 1
    # Find syscalls
    # TODO

    # Getting time
    cTime = datetime.now() - startTime
    signal.signal(signal.SIGINT, original_sigint_handler)

    if (sigint):
        print("\n")
        fatal(
            "SIGINT ended the analysis prematurely, gadget database might be incomplete\n"
        )
        sigint = False
    notify("Gadgets analyzed : " + str(len(pair_list)))
    notify("Successfully translated : " + str(success))
    notify("Computation time : " + str(cTime))

    # Create the database
    db = Database(gadgets)