示例#1
0
def build_mprotect64(addr, size, prot=7, constraint=None, assertion=None, clmax=SYSCALL_LMAX, optimizeLen=False):
    """
    Call mprotect from X86-64 arch
    Args must be on registers (rdi, rsi, rdx):
    Sizes are (unsigned long, size_t, unsigned long)
    rax must be 10 
    """
    # Check args
    if not isinstance(addr, int):
        error("Argument error. Expected integer, got " + str(type(addr)))
        return None
    elif not isinstance(size, int):
        error("Argument error. Expected integer, got " + str(type(size)))
        return None
    elif not isinstance(prot, int):
        error("Argument error. Expected integer, got " + str(type(prot)))
        return None
    
    if( constraint is None ):
        constraint = Constraint()
    if( assertion is None ):
        assertion = Assertion()
    
    # Check if we have the function !
    verbose("Trying to call mprotect() function directly")
    func_call = build_call('mprotect', [addr, size, prot], constraint, assertion, clmax=clmax, optimizeLen=optimizeLen)
    if( not isinstance(func_call, str) ):
        verbose("Success")
        return func_call
    else:
        if( not constraint.chainable.ret ):
            verbose("Coudn't call mprotect(), try direct syscall")
        else:
            verbose("Couldn't call mprotect() and return to ROPChain")
            return None
    
    # Otherwise do the syscall by 'hand' 
    # Set the registers
    args = [[Arch.n2r('rdi'),addr],[Arch.n2r('rsi'), size],[Arch.n2r('rdx'),prot], [Arch.n2r('rax'),10]]
    chain = popMultiple(args, constraint, assertion, clmax-1, optimizeLen)
    if( not chain ):
        verbose("Failed to set registers for the mprotect syscall")
        return None
    # Syscall 
    syscalls = search(QueryType.SYSCALL, None, None, constraint, assertion)
    if( not syscalls ):
        verbose("Failed to find a syscall gadget")
        return None
    else:
        chain.addChain(syscalls[0])
    verbose("Success")
    return chain
示例#2
0
def build_call_linux64(funcName, funcArgs, constraint, assertion, clmax=None, optimizeLen=False):
    # Arguments registers 
    # (Args should go in these registers for x64)
    argsRegsNames = ['rdi','rsi','rdx','rcx', 'r8', 'r9']
    argsRegs = [Arch.n2r(name) for name in argsRegsNames]
    # Find the address of the fonction 
    (funcName2, funcAddr) = getFunctionAddress(funcName)
    if( funcName2 is None ):
        return "Couldn't find function '{}' in the binary".format(funcName)
    
    # Check if bad bytes in function address 
    if( not constraint.badBytes.verifyAddress(funcAddr) ):
        return "'{}' address ({}) contains bad bytes".format(funcName2, string_special('0x'+format(funcAddr, '0'+str(Arch.octets()*2)+'x')))
    
    # Check how many arguments 
    if( len(funcArgs) > 6 ):
        return "Doesn't support function call with more than 6 arguments with Linux X64 calling convention :("
        
    # Find a gadget for the fake return address
    if( funcArgs ):
        # Build the ropchain with the arguments
        args_chain = popMultiple(map(lambda x,y:(x,)+y,  argsRegs[:len(funcArgs)], funcArgs), constraint, assertion, clmax=clmax, optimizeLen=optimizeLen)
        if( not args_chain):
            return "Couldn't load arguments in registers"
    else:
        # No arguments 
        args_chain = ROPChain()
    
    # Build call chain (function address + fake return address)
    return args_chain.addPadding(funcAddr, comment=string_ropg(funcName2))
示例#3
0
def build_mprotect64(addr,
                     size,
                     prot=7,
                     constraint=None,
                     assertion=None,
                     clmax=None,
                     optimizeLen=False):
    """
    Call mprotect from X86-64 arch
    Args must be on registers (rdi, rsi, rdx):
    Sizes are (unsigned long, size_t, unsigned long)
    rax must be 10 
    """
    # Check args
    if not isinstance(addr, int):
        error("Argument error. Expected integer, got " + str(type(addr)))
        return None
    elif not isinstance(size, int):
        error("Argument error. Expected integer, got " + str(type(size)))
        return None
    elif not isinstance(prot, int):
        error("Argument error. Expected integer, got " + str(type(prot)))
        return None

    if (constraint is None):
        constraint = Constraint()
    if (assertion is None):
        assertion = Assertion()

    # Set the registers
    args = [[Arch.n2r('rdi'), addr], [Arch.n2r('rsi'), size],
            [Arch.n2r('rdx'), prot], [Arch.n2r('rax'), 10]]
    chain = popMultiple(args, constraint, assertion, clmax - 1, optimizeLen)
    if (not chain):
        verbose("Failed to set registers for the mprotect syscall")
        return None
    # Syscall
    syscalls = search(QueryType.SYSCALL, None, None, constraint, assertion)
    if (not syscalls):
        verbose("Failed to find a syscall gadget")
        return None
    else:
        chain.addChain(syscalls[0])
    verbose("Success")
    return chain
示例#4
0
def build_mprotect32(addr, size, prot=7, constraint=None, assertion = None, clmax=None, optimizeLen=False):
    """
    Call mprotect from X86 arch
    Args must be on the stack:
    int mprotect(void *addr, size_t len, int prot)
    args must be in registers (ebx, ecx, edx)
    eax must be 0x7d = 125
    """
    # Check args
    if not isinstance(addr, int):
        error("Argument error. Expected integer, got " + str(type(addr)))
        return None
    elif not isinstance(size, int):
        error("Argument error. Expected integer, got " + str(type(size)))
        return None
    elif not isinstance(prot, int):
        error("Argument error. Expected integer, got " + str(type(prot)))
        return None
        
    if( constraint is None ):
        constraint = Constraint()
    if( assertion is None ):
        assertion = Assertion()
    
    # Set the registers
    args = [[Arch.n2r('eax'),0x7d],[Arch.n2r('ebx'), addr],[Arch.n2r('ecx'),size], [Arch.n2r('edx'),prot]]
    chain = popMultiple(args, constraint, assertion, clmax-1, optimizeLen)
    if( not chain ):
        verbose("Failed to set registers for the mprotect syscall")
        return None
    # Int 0x80
    int80_gadgets = search(QueryType.INT80, None, None, constraint, assertion)
    if( not int80_gadgets ):
        verbose("Failed to find an 'int 80' gadget")
        return None
    else:
        chain.addChain(int80_gadgets[0])
    verbose("Success")
    return chain
示例#5
0
def parse_keep_regs(string):
    """
    Parses a 'keep registers' string into a list of register uids
    Input: a string of format like "rax,rcx,rdi"
    Output if valid string (True, list) where list = 
        [1, 3, 4] (R1 is rax, R3 is RCX, ... )
    Output if invalid string (False, error_message)
    """
    user_keep_regs = string.split(',')
    keep_regs = set()
    for reg in user_keep_regs:
        if (reg in Arch.regNameToNum):
            keep_regs.add(Arch.n2r(reg))
        else:
            return (False, "Error. '{}' is not a valid register".format(reg))
    return (True, list(keep_regs))
示例#6
0
 def getSemantics(self, value):
     if( isinstance( value, Expr)):
         return self.semantics.get(value)
     else:
         # Try to translate into a reg 
         if( isinstance(value, int)):
             num = value
         elif( value in Arch.regNameToNum ):
             num = Arch.n2r(value)
         else:
             return []
         # Return corresponding if present 
         if( num in self.graph.lastMod ):
             reg = SSAReg(num, self.graph.lastMod[num])
             return self.semantics.get(reg)
         # Or return the same
         else:
             return [SPair(SSAExpr(num, 0), CTrue())]
示例#7
0
 def possiblePopOffsets(self, reg, constraint, assertion):
     global gadgets
     res = dict()
     lookUp = self.types[QueryType.MEMtoREG][reg]\
              .registers.get(Arch.n2r(Arch.currentArch.sp), None)
     if (lookUp is None):
         return dict()
     for cst in lookUp.values:
         tmp = []
         for i in range(0, len(lookUp.values[cst])):
             gadget = gadgets[lookUp.values[cst][i]]
             (status, conds) = constraint.verify(gadget)
             if (status):
                 # if yes, check if the assertion verifies the constraint
                 remaining = assertion.filter(
                     conds + [lookUp.preConditions[cst][i]])
                 if (not remaining):
                     tmp.append(gadget)
         res[cst] = tmp
     return res
示例#8
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
示例#9
0
def build_mprotect32(addr,
                     size,
                     prot=7,
                     constraint=None,
                     assertion=None,
                     clmax=SYSCALL_LMAX,
                     optimizeLen=False):
    """
    Call mprotect from X86 arch
    Args must be on the stack:
    int mprotect(void *addr, size_t len, int prot)
    args must be in registers (ebx, ecx, edx)
    eax must be 0x7d = 125
    """
    # Check args
    if not isinstance(addr, int):
        error("Argument error. Expected integer, got " + str(type(addr)))
        return None
    elif not isinstance(size, int):
        error("Argument error. Expected integer, got " + str(type(size)))
        return None
    elif not isinstance(prot, int):
        error("Argument error. Expected integer, got " + str(type(prot)))
        return None

    if (constraint is None):
        constraint = Constraint()
    if (assertion is None):
        assertion = Assertion()

    # Check if we have the function !
    verbose("Trying to call mprotect() function directly")
    func_call = build_call('mprotect', [addr, size, prot],
                           constraint,
                           assertion,
                           clmax=clmax,
                           optimizeLen=optimizeLen)
    if (not isinstance(func_call, str)):
        verbose("Success")
        return func_call
    else:
        if (not constraint.chainable.ret):
            verbose("Coudn't call mprotect(), try direct syscall")
        else:
            verbose("Couldn't call mprotect() and return to ROPChain")
            return None

    # Otherwise do syscall directly
    # Set the registers
    args = [[Arch.n2r('eax'), 0x7d], [Arch.n2r('ebx'), addr],
            [Arch.n2r('ecx'), size], [Arch.n2r('edx'), prot]]
    chain = popMultiple(args, constraint, assertion, clmax - 1, optimizeLen)
    if (not chain):
        verbose("Failed to set registers for the mprotect syscall")
        return None
    # Int 0x80
    int80_gadgets = search(QueryType.INT80, None, None, constraint, assertion)
    if (not int80_gadgets):
        verbose("Failed to find an 'int 80' gadget")
        return None
    else:
        chain.addChain(int80_gadgets[0])
    verbose("Success")
    return chain
示例#10
0
def build_syscall_Linux(syscall,
                        arg_list,
                        arch_bits,
                        constraint=None,
                        assertion=None,
                        clmax=SYSCALL_LMAX,
                        optimizeLen=False):
    """
    arch_bits = 32 or 64 :) 
    """
    # Check args
    if (syscall.nb_args() != len(arg_list)):
        error("Error. Expected {} arguments, got {}".format(
            len(syscall.arg_types), len(arg_list)))
        return None
    # Check args length
    for i in range(0, len(arg_list)):
        if (not verifyArgType(arg_list[i], syscall.arg_types[i])):
            error("Argument error for '{}': expected '{}', got '{}'".format(
                arg_list[i], syscall.arg_types[i], type(arg_list[i])))
            return None
    # Check constraint and assertion
    if (constraint is None):
        constraint = Constraint()
    if (assertion is None):
        assertion = getBaseAssertion()

    # Check if we have the function !
    verbose("Trying to call {}() function directly".format(syscall.def_name))
    func_call = build_call(syscall.function(),
                           arg_list,
                           constraint,
                           assertion,
                           clmax=clmax,
                           optimizeLen=optimizeLen)
    if (not isinstance(func_call, str)):
        verbose("Success")
        return func_call
    else:
        if (not constraint.chainable.ret):
            verbose("Coudn't call {}(), try direct syscall".format(
                syscall.def_name))
        else:
            verbose("Couldn't call {}() and return to ROPChain".format(
                syscall.def_name))
            return None

    # Otherwise do syscall directly
    # Set the registers
    args = [(Arch.n2r(x[0]), x[1])
            for x in zip(syscall.arg_regs, arg_list) + syscall.syscall_arg_regs
            ]
    chain = popMultiple(args,
                        constraint,
                        assertion,
                        clmax - 1,
                        optimizeLen=optimizeLen)
    if (not chain):
        verbose("Failed to set registers for the mprotect syscall")
        return None
    # Int 0x80
    if (arch_bits == 32):
        syscall_gadgets = search(QueryType.INT80, None, None, constraint,
                                 assertion)
    # syscall
    elif (arch_bits == 64):
        syscall_gadgets = search(QueryType.SYSCALL, None, None, constraint,
                                 assertion)
    if (not syscall_gadgets):
        verbose("Failed to find an 'int 0x80' OR 'syscall' gadget")
        return None
    else:
        chain.addChain(syscall_gadgets[0])
    verbose("Success")
    return chain