Esempio n. 1
0
def append_segment(segment_name):
    """ Add a new segment to the IDB file and return its starting address.
    Information about function arguments will be stored here. Only works if the
    segment name is not used yet. This does not affect the original binary.

    Arguments:
    segment_name -- the name of the segment to be added
    """
    for segment in idautils.Segments():
        if idc.SegName(segment) == segment_name:
            g_logger.warning('Segment ' + segment_name + ' already exists')
            return idc.SegStart(segment)

    new_segment_start = get_end_of_last_segment()
    g_logger.debug('Adding new segment at 0x%08x' % new_segment_start)
    if not idc.AddSeg(new_segment_start,
                      (new_segment_start + NEW_SEGMENT_SIZE), 0, 1, 0,
                      idaapi.scPub) == 1:
        raise FailedToAppendSegmentException('Could not add segment')
    # set new segment's attributes
    if not idc.RenameSeg(new_segment_start, segment_name):
        raise FailedToAppendSegmentException('Could not rename segment')
    if not idc.SetSegClass(new_segment_start, 'DATA'):
        raise FailedToAppendSegmentException('Could not set segment class')
    if not idc.SegAlign(new_segment_start, idc.saRelPara):
        raise FailedToAppendSegmentException('Could not align segment')
    if not idc.SetSegAddressing(new_segment_start, 1):  # 1 -- 32 bit
        raise FailedToAppendSegmentException(
            'Could not set segment addressing')
    return new_segment_start
Esempio n. 2
0
def main(argv=None):
    if argv is None:
        argv = sys.argv[:]

    try:
        seg = prompt_for_segment()
    except BadInputError:
        logger.error('bad input, exiting...')
        return -1

    with open(seg.path, 'rb') as f:
        buf = f.read()

    seglen = len(buf)
    if seglen % 0x1000 != 0:
        seglen = seglen + (0x1000 - (seglen % 0x1000))

    if not idc.AddSeg(seg.addr, seg.addr + seglen, 0, 1, 0, idaapi.scPub):
        logger.error('failed to add segment: 0x%x', seg.addr)
        return -1

    if not idc.RenameSeg(seg.addr, seg.name):
        logger.warning('failed to rename segment: %s', seg.name)

    if not idc.SetSegClass(seg.addr, 'CODE'):
        logger.warning('failed to set segment class CODE: %s', seg.name)

    if not idc.SegAlign(seg.addr, idc.saRelPara):
        logger.warning('failed to align segment: %s', seg.name)

    idaapi.patch_many_bytes(seg.addr, buf)
Esempio n. 3
0
    def make_segment(self, offset, size, class_name="DATA", name="pe_map", data=None):
        """Create a new section in the IDB"""
        idc.AddSeg(offset, offset + size, 0, 1, 0, idaapi.scPub)
        idc.RenameSeg(offset, str(name))
        idc.SetSegClass(offset, str(class_name))
        #idc.SegAlign(offset, idc.saRelPara)
        if data:
            idaapi.patch_many_bytes(offset, bytes(data))

        self.ret = None
        return self.ret
Esempio n. 4
0
def map_shared_bridges(dsc_file, adrfind):
    """ finds branch islands in a given dyld_shared_cache file,
        maps them to IDA's db and extract its addresses """
    dsc_file.seek(0, 2)
    filesize = dsc_file.tell()
    dsc_file.seek(0)
    ACCESS_READ = 1
    a = mmap.mmap(dsc_file.fileno(), length=filesize, access=ACCESS_READ)
    reexp = re.compile(
        "\xcf\xfa\xed\xfe.{340,360}dyld_shared_cache_branch_islands")
    print "[+] scanning dsc for BRANCH ISLANDS"
    # this list will hold all our branch_islands segments
    branch_islands_segments = []
    jmp_to_code = collections.defaultdict(list)
    for ma in reexp.finditer(a):
        print "[+] WRITING BRANCH ISLAND: 0x%08X" % (ma.start())
        fif = FileInFile(dsc_file, ma.start())
        m = MachO_patched(fif)
        if _IN_IDA:
            for seg in m.segments:
                for sec in seg.sections:
                    idc.AddSegEx(sec.addr, sec.addr + sec.size, 0, 0,
                                 idaapi.saRelPara, idaapi.scPub,
                                 idc.ADDSEG_FILLGAP)
                    name = "branch_islands_%X%s%s" % (ma.start(), seg.segname,
                                                      sec.sectname)
                    idc.RenameSeg(sec.addr, name)
                    idc.SetSegClass(sec.addr, "CODE")
                    idc.SetSegAddressing(sec.addr, 2)
                    dsc_file.seek(sec.offset)
                    memcpy(sec.addr, dsc_file.read(sec.size))
                    branch_islands_segments.append(sec.addr)
                    # make code
                    codeea = sec.addr
                    print "Going through the code!"
                    while codeea < (sec.addr + sec.size):
                        res = idc.MakeCode(codeea)
                        if not res:
                            print "[!] EA:0x%X ERR while making code" % codeea
                            codeea += 4
                            continue

                        d = idc.GetDisasm(codeea)
                        # if it's a "B     0x4dd13550"
                        if d.startswith("B "):
                            addr = d.split()[1]
                            if addr.startswith("0x"):
                                branchaddr = int(addr, 16)
                                jmp_to_code[branchaddr].append(codeea)
                                #   idc.MakeRptCmt(codeea, "0x%X was taken!" % branchaddr)

                        codeea = idc.FindUnexplored(codeea, idc.SEARCH_DOWN)
    label_and_fix_branch_islands(dsc_file, adrfind, jmp_to_code)
Esempio n. 5
0
def addSegmentAtLast(segs, segSize):
    si = SegmInfo()
    si.m_startAddr = segs[-1].m_endAddr
    si.m_endAddr = si.m_startAddr + segSize
    si.m_name = ".MySeg"
    si.m_className = "CODE"

    # https://www.hex-rays.com/products/ida/support/idapython_docs/
    # startea - linear address of the start of the segment
    # endea - linear address of the end of the segment this address will not belong to the segment 'endea' should be higher than 'startea'
    # base - base paragraph or selector of the segment. a paragraph is 16byte memory chunk. If a selector value is specified, the selector should be already defined.
    # use32 - 0: 16bit segment, 1: 32bit segment, 2: 64bit segment
    # align - segment alignment. see below for alignment values
    # comb - segment combination. see below for combination values.
    ret = idc.AddSeg(si.m_startAddr, si.m_endAddr, 0, 2, 0, 0)
    if ret == False:
        print "Create segment failed"
        return None

    # Reset this segment
    byte = 0x90
    for ea in range(si.m_startAddr, si.m_endAddr, 1):
        PatchByte(ea, byte)
        # ret = MakeCode(ea)
        # if ret == 0:
        #     print "Make code failed at this section"
        #     return 0

    # Set segment's attribute
    # https://reverseengineering.stackexchange.com/questions/2394/how-can-i-change-the-read-write-execute-flags-on-a-segment-in-ida
    # idc.SetSegmentAttr(si.m_startAddr, idc.SEGATTR_PERM, idc.SEGPERM_EXEC | idc.SEGPERM_WRITE | idc.SEGPERM_READ)
    ret = idc.SetSegmentAttr(si.m_startAddr, idc.SEGATTR_PERM, 1 | 2 | 4)
    if ret == 0:
        print "Set segment attribute failed"
    ret = idc.SetSegClass(si.m_startAddr, si.m_className)
    if ret == 0:
        print "Set segment class failed"
    ret = idc.SetSegmentType(si.m_startAddr, idc.SEG_CODE)
    if ret == 0:
        print "Set segment type to code failed"

    return si
    def __to_native(self, function, is_recursive_mode=False, fixupfile=None):
        """
            Process translating VM byte code to native machine code
            :param function: Function descriptor
            :param is_recursive_mode: Enable recursive mode
            :param fixupfile: Path to fixup file
            :return:  Address of new segment where were native code wrote
        """
        print "[+] Translate begin. Function %s" % hex(function.begin_ea)
        ks = None

        if self.mode == 32:
            ks = Ks(KS_ARCH_X86, KS_MODE_32)
        else:
            ks = Ks(KS_ARCH_X86, KS_MODE_64)

        locs = {
            function.graph.nodes[na].begin_ea
            for na in function.graph.nodes
        }
        func_addresses = []
        for x in function.graph.nodes:
            for y in range(
                    function.graph.nodes[x].begin_ea,
                    function.graph.nodes[x].end_ea + self.instruction_size,
                    self.instruction_size):
                func_addresses.append(y)

        func_ins = {x: self.instructions[x] for x in func_addresses}

        vr0x86_blocks = self.get_vr0blocks(func_ins)

        print "[+] Blocks for %s" % hex(function.begin_ea).replace("L", "")
        i = 0
        for pc in vr0x86_blocks.keys():
            c_vr0, c_end_vr0_block = vr0x86_blocks[pc]
            print "----BLOCK %s----" % i
            print "   -> [?] Block begin: %s" % hex(pc).replace("L", "")
            print "   -> [?] Block end: %s" % hex(c_end_vr0_block).replace(
                "L", "")
            print "   -> [?] Block vr0: %s" % c_vr0
            i += 1

        labels = {}
        li = 0
        for loc in locs:
            labels[loc] = "label_%s" % li
            li += 1

        function_real_base = function.machine_handler
        print "[+] Real function base: %s" % hex(function_real_base).replace(
            "L", "")

        if self.mode == 32:
            asm_text = self._asm_creator_x86(
                func_ins,
                labels,
                vr0x86_blocks,
                function.machine_handler,
                is_recursive_mode=is_recursive_mode,
                fixupfile=fixupfile)
        else:
            asm_text = self._asm_creator_x64(
                func_ins,
                labels,
                vr0x86_blocks,
                function.machine_handler,
                is_recursive_mode=is_recursive_mode,
                fixupfile=fixupfile)

        print asm_text

        segs = list(idautils.Segments())
        last_seg_ea = idc.SegEnd(segs[len(segs) - 1])

        encoding, count = ks.asm(asm_text, addr=last_seg_ea)

        seg_name = ".devirt_%s" % function.name
        seg_size = len(encoding) + self.machine_word_size
        if not idc.AddSeg(last_seg_ea, last_seg_ea + seg_size, 0, 1, 0,
                          idaapi.scPub):
            print "[~] Can't create segment at address %s" % hex(last_seg_ea)
            return

        if not idc.RenameSeg(last_seg_ea, seg_name):
            print "[!] Failed rename segment. Segment name %s" % seg_name

        if not idc.SetSegClass(last_seg_ea, 'CODE'):
            print "[!] Failed set CODE class. Segment name %s" % seg_name

        if not idc.SegAlign(last_seg_ea, idc.saRelPara):
            print "[!] Failed set align. Segment name %s" % seg_name

        bitness = 1
        if self.mode == 64:
            bitness = 2

        if not idc.SetSegAddressing(last_seg_ea, bitness):
            print "[!] Failed set bitness. Segment name %s" % seg_name

        if self.mode == 32:
            idc.PatchDword(last_seg_ea, 0)
        else:
            idc.PatchQword(last_seg_ea, 0)

        last_seg_ea += self.machine_word_size

        waddr = last_seg_ea
        for b in encoding:
            idc.PatchByte(waddr, b)
            waddr += 1

        print "[+] Write binary to: %s" % hex(last_seg_ea).replace("L", "")
        self.devirtualized_functions[function.begin_ea] = (last_seg_ea,
                                                           len(encoding) + 4)
        return last_seg_ea
Esempio n. 7
0
    def set_class(self, value):

        return idc.SetSegClass(self.addr, value)