コード例 #1
0
def _CSTtoREG_transitivity(reg, cst, env, n=1):
    """
    Perform REG1 <- CST with REG1 <- REG2 <- CST
    """
    ID = StrategyType.CSTtoREG_TRANSITIVITY

    ## Test for special cases
    # Test lmax
    if (env.getLmax() <= 0):
        return []
    # Limit number of calls to ...
    elif (env.nbCalls(ID) >= 99):
        return []
    # Check if the cst is in badBytes
    elif (not env.getConstraint().badBytes.verifyAddress(cst)):
        return []
    # Check if previous call was already CSTtoREG_transitivity
    # Reason: we handle the transitivity with REGtoREG transitivity
    # so no need to do it also recursively with this one ;)
    elif (env.callsHistory()[-1] == ID):
        return []

    # Set env
    env.addCall(ID)

    #############################
    res = []
    for inter in Arch.registers():
        if (inter == reg or inter in env.getConstraint().getRegsNotModified()
                or inter == Arch.ipNum() or inter == Arch.spNum()):
            continue
        # Find reg <- inter
        inter_to_reg = _search(QueryType.REGtoREG, reg, (inter, 0), env, n)
        if (inter_to_reg):
            # We found ROPChains s.t reg <- inter
            # Now we want inter <- cst
            min_len = min([len(chain) for chain in inter_to_reg])
            env.subLmax(min_len)
            env.addUnusableReg(reg)
            cst_to_inter = _search(QueryType.CSTtoREG, inter, cst, env,
                                   n / len(inter_to_reg) + 1)
            env.removeUnusableReg(reg)
            env.addLmax(min_len)

            for chain2 in inter_to_reg:
                for chain1 in cst_to_inter:
                    if (len(chain1) + len(chain2) <= env.getLmax()):
                        res.append(chain1.addChain(chain2, new=True))

        # Did we get enough chains ?
        if (len(res) >= n):
            break
    ###############################
    # Restore env
    env.removeCall(ID)

    return res[:n]
コード例 #2
0
def _MEMtoREG_transitivity(reg, arg2, env, n=1):
    """
    Perform reg <- inter <- mem(arg2)
    """
    ID = StrategyType.MEMtoREG_TRANSITIVITY

    ## Test for special cases
    # Test lmax
    if (env.getLmax() <= 0):
        return FailRecord(lmax=True)
    # Limit number of calls to ...
    elif (env.nbCalls(ID) >= 99):
        return FailRecord()
    # Check if previous call was already MEMtoREG_transitivity
    # Reason: we handle the transitivity with REGtoREG transitivity
    # so no need to do it also recursively with this one ;)
    elif (env.callsHistory()[-1] == ID):
        return FailRecord()

    # Set env
    env.addCall(ID)

    ###########################
    res = []
    res_fail = FailRecord()
    for inter in Arch.registers():
        if (inter == reg or inter in env.getConstraint().getRegsNotModified()
                or inter == Arch.ipNum() or inter == Arch.spNum()):
            continue

        # Find arg1 <- inter
        inter_to_reg = _search(QueryType.REGtoREG, reg, (inter, 0), env, n)
        if (inter_to_reg):
            min_len = min([len(chain) for chain in inter_to_reg])
            # Try to find inter <- arg2
            env.subLmax(min_len)
            env.addUnusableReg(reg)
            arg2_to_inter = _search(QueryType.MEMtoREG, inter, arg2, env, n)
            env.removeUnusableReg(reg)
            env.addLmax(min_len)
            if (not arg2_to_inter):
                res_fail.merge(arg2_to_inter)
                continue
            res += [chain1.addChain(chain2, new=True) for chain1 in arg2_to_inter \
                for chain2 in inter_to_reg if len(chain1)+len(chain2) <= env.getLmax()  ]
        else:
            res_fail.merge(inter_to_reg)
        # Did we get enough chains ?
        if (len(res) >= n):
            break
    ########################

    # Restore env
    env.removeCall(ID)
    return res[:n] if res else res_fail
コード例 #3
0
def _REGtoMEM_transitivity(arg1, arg2, env, n=1):
    """
    reg <- arg2
    mem(arg1) <- reg
    """
    ID = StrategyType.REGtoMEM_TRANSITIVITY

    ## Test for special cases
    # Test lmax
    if (env.getLmax() <= 0):
        return FailRecord(lmax=True)
    # Limit number of calls to ...
    elif (env.nbCalls(ID) >= 99):
        return FailRecord()
    # Check if previous call was already REGtoMEM_transitivity
    # Reason: we handle the transitivity with REGtoREG transitivity
    # so no need to do it also recursively with this one ;)
    elif (env.callsHistory()[-1] == ID):
        return FailRecord()

    # Set env
    env.addCall(ID)
    ###################################
    res = []
    res_fail = FailRecord()
    for inter in Arch.registers():
        if (inter == arg2[0]
                or inter in env.getConstraint().getRegsNotModified()
                or inter == Arch.ipNum() or inter == Arch.spNum()):
            continue
        # Find inter <- arg2
        arg2_to_inter = _search(QueryType.REGtoREG, inter, (arg2[0], arg2[1]),
                                env, n)
        if (arg2_to_inter):
            len_min = min([len(chain) for chain in arg2_to_inter])
            # Try to find mem(arg1) <- inter
            env.subLmax(len_min)
            env.addUnusableReg(arg2[0])
            inter_to_mem = _search(QueryType.REGtoMEM, arg1, (inter, 0), env)
            env.removeUnusableReg(arg2[0])
            env.addLmax(len_min)
            if (not inter_to_mem):
                res_fail.merge(inter_to_mem)
                continue
            res += [chain1.addChain(chain2, new=True) for chain1 in arg2_to_inter\
                for chain2 in inter_to_mem if len(chain1)+len(chain2) <= env.getLmax()]
            if (len(res) >= n):
                break
        else:
            res_fail.merge(arg2_to_inter)
    #####################################
    # Resotre env
    env.removeCall(ID)
    return res if res else res_fail
コード例 #4
0
def init_impossible_REGtoREG(env):
    global INIT_LMAX, INIT_MAXDEPTH
    global baseAssertion
    # DEBUG
    #try:
    startTime = datetime.now()
    i = 0
    impossible_count = 0
    for reg1 in sorted(Arch.registers()):
        reg_name = Arch.r2n(reg1)
        if (len(reg_name) < 6):
            reg_name += " " * (6 - len(reg_name))
        elif (len(reg_name) >= 6):
            reg_name = reg_name[:5] + "."
        for reg2 in Arch.registers():
            i += 1
            charging_bar(len(Arch.registers() * len(Arch.registers())), i, 30)
            if (reg2 == reg1 or reg2 == Arch.ipNum()):
                continue
            _search(QueryType.REGtoREG, reg1, (reg2, 0), env, n=1)
            if (env.checkImpossible_REGtoREG(reg1, reg2, 0)):
                impossible_count += 1
    cTime = datetime.now() - startTime
    # Get how many impossible path we found
    impossible_rate = int(100 * (float(impossible_count) / float(
        (len(Arch.registers()) - 1) * len(Arch.registers()))))
    notify('Optimization rate : {}%'.format(impossible_rate))
    notify("Computation time : " + str(cTime))
コード例 #5
0
def init_impossible_REGtoREG(env):
    global INIT_LMAX, INIT_MAXDEPTH
    global baseAssertion

    try:
        startTime = datetime.now()
        i = 0
        impossible_count = 0
        for reg1 in sorted(Arch.registers()):
            reg_name = Arch.r2n(reg1)
            if (len(reg_name) < 6):
                reg_name += " " * (6 - len(reg_name))
            elif (len(reg_name) >= 6):
                reg_name = reg_name[:5] + "."
            for reg2 in Arch.registers():
                i += 1
                charging_bar(len(Arch.registers() * len(Arch.registers())), i,
                             30)
                if (reg2 == reg1 or reg2 == Arch.ipNum()):
                    continue
                _search(QueryType.REGtoREG, reg1, (reg2, 0), env, n=1)
                if (env.checkImpossible_REGtoREG(reg1, reg2, 0)):
                    impossible_count += 1
        cTime = datetime.now() - startTime
        # Get how many impossible path we found
        impossible_rate = int(100 * (float(impossible_count) / float(
            (len(Arch.registers()) - 1) * len(Arch.registers()))))
        notify('Optimization rate : {}%'.format(impossible_rate))
        notify("Computation time : " + str(cTime))
    except:
        print("\n")
        fatal("Exception caught, stopping Semantic Engine init process...\n")
        fatal("Search time might get very long !\n")
        env = SearchEnvironment(INIT_LMAX, Constraint(), baseAssertion,
                                INIT_MAXDEPTH)
コード例 #6
0
def initEngine():
    global INIT_LMAX, INIT_MAXDEPTH
    global global_impossible_REGtoREG
    global baseAssertion

    # Init global variables
    baseAssertion = Assertion().add(\
            RegsValidPtrRead([(Arch.spNum(),-5000, 10000)]), copy=False).add(\
            RegsValidPtrWrite([(Arch.spNum(), -5000, 0)]), copy=False).add(\
            RegsNoOverlap([(Arch.spNum(), reg) for reg in Arch.registers()]))

    info(string_bold("Initializing Semantic Engine\n"))

    # Init helper for REGtoREG
    global_impossible_REGtoREG = SearchEnvironment(INIT_LMAX, Constraint(),
                                                   baseAssertion,
                                                   INIT_MAXDEPTH)
    init_impossible_REGtoREG(global_impossible_REGtoREG)
コード例 #7
0
def _CSTtoMEM_write(arg1, cst, env, n=1):
    """
    reg <- cst 
    mem(arg2) <- reg
    """
    ID = StrategyType.CSTtoMEM_WRITE

    ## Test for special cases
    # Test lmax
    if (env.getLmax() <= 0):
        return FailRecord(lmax=True)
    # Limit number of calls to ...
    elif (env.nbCalls(ID) >= 99):
        return FailRecord()

    # Set env
    env.addCall(ID)
    ######################################
    res = []
    res_fail
    addr_reg = arg1[0]
    addr_cst = arg1[1]
    # 1. First strategy (direct)
    # reg <- cst
    # mem(arg1) <- reg
    for reg in Arch.registers():
        if (reg == Arch.ipNum() or reg == Arch.spNum() or reg == addr_reg):
            continue
        # Find reg <- cst
        constraint = env.getConstraint()
        env.setConstraint(constraint.add(RegsNotModified([addr_reg])))
        env.subLmax(1)
        cst_to_reg_chains = _search(QueryType.CSTtoREG, reg, cst, env, n)
        env.addLmax(1)
        env.setConstraint(constraint)
        if (not cst_to_reg_chains):
            res_fail.merge(cst_to_reg_chains)
            continue
        # Search for mem(arg1) <- reg
        # We get all reg2,cst2 s.t mem(arg1) <- reg2+cst2
        possible_mem_writes = DBPossibleMemWrites(addr_reg,
                                                  addr_cst,
                                                  env.getConstraint(),
                                                  env.getAssertion(),
                                                  n=1)
        # 1.A. Ideally we look for reg2=reg and cst2=0 (direct_writes)
        possible_mem_writes_reg = possible_mem_writes.get(reg)
        if (possible_mem_writes_reg):
            direct_writes = possible_mem_writes[reg].get(0, [])
        else:
            direct_writes = []
        padding = constraint.getValidPadding(Arch.octets())
        for write_gadget in direct_writes:
            for cst_to_reg_chain in cst_to_reg_chains:
                # Pad the gadgets
                write_chain = ROPChain([write_gadget])
                for i in range(0, write_gadget.spInc - Arch.octets(),
                               Arch.octets()):
                    write_chain.addPadding(padding)
                full_chain = cst_to_reg_chain.addChain(write_chain, new=True)
                if (len(full_chain) <= env.getLmax()):
                    res.append(full_chain)
                if (len(res) >= n):
                    break
            if (len(res) >= n):
                break
        if (len(res) >= n):
            break
        # 1.B. Otherwise we try to adjust the cst2
        # To be implemented

    # 2d Strategy: indirect
    # reg <- arg2 - cst
    # mem(arg1) <- reg + cst

    # TO IMPLEMENT IN ANOTHER FUNCTION !

    ###################
    # Restore env
    env.removeCall(ID)
    return res if res else res_fail
コード例 #8
0
def _REGtoREG_transitivity(arg1, arg2, env, n=1):
    """
    Perform REG1 <- REG2+CST with REG1 <- REG3 <- REG2+CST
    """
    ID = StrategyType.REGtoREG_TRANSITIVITY

    ## Test for special cases
    # Test lmax
    if (env.getLmax() <= 0):
        return FailRecord(lmax=True)
    # If reg1 <- reg1 + 0, return
    elif (arg1 == arg2[0] and arg2[1] == 0):
        return FailRecord()
    # Limit number of calls to REGtoREG transitivity
    elif (env.callsHistory()[-2:] == [ID, ID]):
        return FailRecord()

    # Set env
    env.addCall(ID)

    # Search
    res = []
    res_fail = FailRecord()
    for inter_reg in Arch.registers():
        if( inter_reg == arg1 or (inter_reg == arg2[0] and arg2[1]==0)\
            or (env.checkImpossible_REGtoREG(arg1, inter_reg, 0))\
            or (env.checkImpossible_REGtoREG(inter_reg, arg2[0], arg2[1]))\
            or inter_reg == Arch.ipNum() or inter_reg == Arch.spNum() ):
            continue
        # Find reg1 <- inter_reg without using arg2
        env.addUnusableReg(arg2[0])
        env.subLmax(1)
        inter_to_arg1_list = _search(QueryType.REGtoREG, arg1, (inter_reg, 0),
                                     env, n)
        env.removeUnusableReg(arg2[0])
        env.addLmax(1)
        if (not inter_to_arg1_list):
            res_fail.merge(inter_to_arg1_list)
            continue
        else:
            min_len_chain = min([len(chain) for chain in inter_to_arg1_list])

        # Find inter_reg <- arg2 without using arg1
        env.addUnusableReg(arg1)
        env.subLmax(min_len_chain)
        n2 = n / len(inter_to_arg1_list)
        if (n2 == 0):
            n2 = 1

        arg2_to_inter_chains = _search(QueryType.REGtoREG, inter_reg, arg2,
                                       env, n2)
        if (not arg2_to_inter_chains):
            res_fail.merge(arg2_to_inter_chains)
            continue
        for arg2_to_inter in arg2_to_inter_chains:
            for inter_to_arg1 in inter_to_arg1_list:
                if (len(inter_to_arg1) + len(arg2_to_inter) <= env.getLmax()):
                    res.append(arg2_to_inter.addChain(inter_to_arg1, new=True))
                if (len(res) >= n):
                    break
            if (len(res) >= n):
                break
        env.addLmax(min_len_chain)
        env.removeUnusableReg(arg1)
        if (len(res) >= n):
            break
    # Restore env
    env.removeCall(ID)
    return res if res else res_fail