Ejemplo n.º 1
0
    def disassemble(self):
        """
        Dump .text, .rodata, .data, .eh_frame, .got to file
        """
        print colored('1: DISASSEMBLE', 'green')
        ret = os.system(config.objdump + ' -Dr -j .text ' + self.file + ' > ' +
                        self.file + '.temp')
        self.checkret(ret, self.file + '.temp')

        if not ELF_utils.elf_arm():
            if ELF_utils.elf_32():
                pic_process.picprocess32(self.file)
            else:
                extern_symbol_process.globalvar(self.file)
                pic_process.picprocess64(self.file)

        ret = os.system(
            config.objdump + " -s -j .rodata " + self.file +
            " | grep \"^ \" | cut -d \" \" -f3,4,5,6 > rodata.info")
        self.checkret(ret, 'rodata.info')
        ret = os.system(config.objdump + " -s -j .data " + self.file +
                        " | grep \"^ \" | cut -d \" \" -f3,4,5,6 > data.info")
        self.checkret(ret, 'data.info')
        os.system(config.objdump + " -s -j .eh_frame " + self.file +
                  " | grep \"^ \" | cut -d \" \" -f3,4,5,6 > eh_frame.info")
        if not ELF_utils.elf_arm():
            os.system(
                config.objdump + " -s -j .eh_frame_hdr " + self.file +
                " | grep \"^ \" | cut -d \" \" -f3,4,5,6 > eh_frame_hdr.info")
        os.system(config.objdump + " -s -j .got " + self.file +
                  " | grep \"^ \" | cut -d \" \" -f3,4,5,6 > got.info")
Ejemplo n.º 2
0
 def traverse32(self, l, startaddr):
     """
     Traverse data section, find pointers using 32bit alignment and substitute them with labels
     :param l: .byte declaration list
     :param startaddr: section start address
     """
     i = 0
     holei = 0
     while holei < len(self.exclude) and startaddr > self.exclude[holei][1]:
         holei += 1
     while i < len(l) - 3:
         val = int(''.join(map(lambda e: e[1][8:10], reversed(l[i:i + 4]))),
                   16)
         s = self.check_sec(val)
         if s is not None:
             if self.assumption_two:
                 self.in_jmptable = False
             elif not ELF_utils.elf_arm() or self.checkifprobd2dARM(val):
                 if s.sec_name == '.plt' and val in self.plt_symbols:
                     l[i] = (l[i][0], '.long ' + self.plt_symbols[val])
                     l[i + 1:i + 4] = [('', '')] * 3
                 else:
                     self.data_labels.insert(0, (s.sec_name, val))
                     l[i] = (l[i][0], '.long S_0x%X' % val)
                     l[i + 1:i + 4] = [('', '')] * 3
         else:
             if ELF_utils.elf_arm(): val = val & (-2)
             if self.check_text(val):
                 c = bbn_byloc(
                     val,
                     self.begin_addrs) if self.assumption_three else True
                 if c or (not c and self.check_jmptable(l[i][0], val)):
                     if c and self.check_jmptable_1(l[i][0]):
                         self.in_jmptable = True
                         self.cur_func_name = self.fn_byloc(val)
                     else:
                         self.in_jmptable = False
                     self.text_labels.insert(0, val)
                     l[i] = (l[i][0], '.long S_0x%X' % val)
                     l[i + 1:i + 4] = [('', '')] * 3
                 else:
                     self.in_jmptable = False
             else:
                 self.in_jmptable = False
         if holei < len(self.exclude) and self.exclude[holei][
                 0] <= startaddr + i + 4 <= self.exclude[holei][1]:
             i = self.exclude[holei][1] - startaddr
             i += 4 - i % 4
             holei += 1
         else:
             i += 4
Ejemplo n.º 3
0
    def data_output(self):
        """
        Save data sections to files
        """
        self.process(self.locations)
        self.process(self.data_labels, True)
        self.gotexternals()
        if len(self.rodata_list) != 0:
            l, s = self.rodata_list[0]
            self.rodata_list[0] = ('s_dummy:\n' + l, s)
        dataalign = '\n.align 16' if ELF_utils.elf_64() else (
            '\n.align 2' if ELF_utils.elf_arm() else '')
        self.rodata_list.insert(0, ('.section .rodata' + dataalign, ''))
        self.got_list.insert(0, ('.section .got', ''))
        self.data_list.insert(0, ('.section .data' + dataalign, ''))
        self.bss_list.insert(0, ('.section .bss' + dataalign, ''))

        def createout(l):
            l = filter(lambda e: len(e[0]) + len(e[1]) > 0, l)
            return '\n'.join(map(lambda e: e[0] + e[1], l))

        with open('final_data.s', 'a') as f:
            f.write(createout(self.rodata_list) + '\n')
            f.write('\n' + createout(self.data_list) + '\n')
            f.write('\n' + createout(self.got_list) + '\n')
            f.write('\n' + createout(self.bss_list) + '\n')
Ejemplo n.º 4
0
 def add_func_label(self, ufuncs, instrs):
     """
     Insert function labels
     :param ufuncs: function list
     :param instrs: instruction list
     :return: instruction list with function declarations
     """
     i = 0
     j = 0
     while True:
         if i == len(ufuncs) or j == len(instrs):
             break
         hf = ufuncs[i]
         hi = instrs[j]
         iloc = get_loc(hi)
         if hf.func_begin_addr == iloc.loc_addr and hf.func_name not in iloc.loc_label:
             lab = '\n' + hf.func_name + ' : '
             if ELF_utils.elf_arm(): lab = '\n.thumb_func' + lab
             iloc.loc_label = lab + iloc.loc_label
             instrs[j] = set_loc(hi, iloc)
             i += 1
             j -= 1
         elif hf.func_begin_addr < iloc.loc_addr:
             i += 1
         j += 1
     return instrs
Ejemplo n.º 5
0
 def process(self):
     """
     Traverse instruction list and insert generated S_ labels in the correct positions
     """
     do_update = lambda s, n: s if n in s else s + '\n' + n
     des1 = self.clean_sort(self.des)
     i = 0
     j = 0
     while True:
         if j == len(des1) or i == len(self.locs):
             break
         # if i == len(self.locs)-1 and j == len(des1)-1:
         #    raise Exception("undefined des list")
         lh = self.locs[i]
         dh = des1[j]
         if dh == lh.loc_addr:
             lhs = 'S_' + dec_hex(lh.loc_addr)
             if ELF_utils.elf_arm() and not isinstance(
                     self.instr_list[i][0], Types.InlineData):
                 lhs = '.thumb_func\n' + lhs
             label = do_update(lh.loc_label, lhs + ' : ')
             self.locs[i].loc_label = label
             j += 1
         elif dh < lh.loc_addr:
             i -= 1
             j += 1
         i += 1
Ejemplo n.º 6
0
 def traverse(self):
     """
     Analyze and modify instructions
     :return: list of generated labels
     """
     if ELF_utils.elf_32() and not ELF_utils.elf_arm():
         self.scan()
     return unify_int_list(self.label)
Ejemplo n.º 7
0
def perform(instrs, funcs):
    # Do stuff to the instruction list
    if not ELF_utils.elf_arm():
        instrs.append(
            Types.TripleInstr(('mov', Types.RegClass('eax'),
                               Types.RegClass('eax'), Types.Loc('', 0,
                                                                True), False)))
    return instrs
Ejemplo n.º 8
0
 def init_array_dump(self):
     return  # This seems creating problems rather than solving them
     if len(self.init_array_list) != 0 and not ELF_utils.elf_arm():
         with open('final_data.s', 'a') as f:
             f.write('\n\n.section .ctors,"aw",@progbits\n')
             f.write('.align 4\n')
             f.write('\n'.join(
                 map(lambda s: '.long ' + s.strip(), self.init_array_list)))
             f.write('\n')
Ejemplo n.º 9
0
def pp_print_file(ilist):
    """
    Write instruction string list to file
    :param ilist: string list
    """
    with open('final.s', 'w') as f:
        f.write('.section .text\n')
        if ELF_utils.elf_arm(): f.write('.syntax unified\n.align 2\n.thumb\n')
        f.write('\n'.join(ilist))
        f.write('\n\n')
Ejemplo n.º 10
0
 def textProcess(self):
     """
     Code disassembly dump
     """
     # useless_func_del.main(self.file)
     if ELF_utils.elf_arm(): arm_process.arm_process(self.file)
     else:
         extern_symbol_process.pltgot(self.file)
         os.system("cat " + self.file +
                   ".temp | grep \"^ \" | cut -f1,3 > instrs.info")
     os.system("cut -f 1 instrs.info > text_mem.info")
Ejemplo n.º 11
0
 def post_analyze(il, re):
     """
     Make final adjustments and write code to file
     :param il: instruction list
     :param re: symbol reconstruction object
     """
     il = re.unify_loc(il)
     if ELF_utils.elf_arm(): il = re.alignvldrARM(il)
     ils = pp_print_list(il)
     ils = re.adjust_globallabel(Analysis.global_bss(), ils)
     pp_print_file(ils)
Ejemplo n.º 12
0
def picprocess32(filepath):
    """
    PC relative operation in x86 32 bit code such as:
     call   804c452 <__x86.get_pc_thunk.bx>
     add    $0x2b8e,%ebx
     mov    $0x10, (%ebx)
    This operation usually loads into %ebx the address of the _GLOBAL_OFFSET_TABLE_
    Further adjustments are operated in the analysis phase
    :param filepath: path to target executable
    """
    if ELF_utils.elf_32() and ELF_utils.elf_exe() and not ELF_utils.elf_arm():
        text_process_strip(filepath)
Ejemplo n.º 13
0
 def lib32_processing(self, instrs, funcs):
     """
     Process PC relative code for x86 32 binaries
     :param instrs: instruction list
     :param funcs: function list
     """
     if ELF_utils.elf_32() and not ELF_utils.elf_arm():
         helper = lib32_helper(instrs, funcs)
         self.label += map(
             lambda addr: (self.check_sec(addr).sec_name, addr),
             helper.traverse())
         return helper.get_instrs()
     return instrs
Ejemplo n.º 14
0
def perform(instrs, funcs):
    """
    Perform gfree instrumentation
    :param instrs: list of program's instruction
    :param funcs: list of function objects
    :return: instrumented list of instructions
    """
    gfree = GfreeInstrumentation(instrs, funcs)
    gfree.findfreebranches()
    gfree.indirectprotection()
    gfree.returnprotection()
    if not ELF_utils.elf_arm(): gfree.rewrite_instr()
    elif config.gfree_ARMITdelete: gfree.remove_its()
    return gfree.instrs
Ejemplo n.º 15
0
 def generatefuncID(self):
     """
     Generate unique function identifier
     :return: integer for x86, integer tuple for ARM
     """
     while True:
         fid = pack('<I', random.getrandbits(32))
         if not fid in self.fIDset:
             if next((b for b in fid if b in alignmentenforce.badbytes),
                     None) is not None:
                 continue
             self.fIDset.add(fid)
             return unpack('<HH', fid) if ELF_utils.elf_arm() \
                    else unpack('<i', fid)[0]
Ejemplo n.º 16
0
def p_exp(exp):
    """
    String from expression
    :param exp: expression
    :return: expression string
    """
    if isinstance(exp, Types.Const): return p_const(exp)
    elif isinstance(exp, Types.Symbol): return p_symbol(exp)
    elif isinstance(exp, Types.AssistOpClass): return p_assist(exp)
    elif isinstance(exp, Types.Ptr): return p_ptraddr(exp)
    elif isinstance(exp, Types.RegClass): return p_reg(exp)
    elif isinstance(exp, Types.Label): return str(exp)
    elif ELF_utils.elf_arm():
        if isinstance(exp, Types.ShiftExp): return p_shift(exp)
        elif isinstance(exp, Types.RegList): return p_reglist(exp)
        elif isinstance(exp, Types.TBExp): return p_tbexp(exp)
Ejemplo n.º 17
0
 def visit_heuristic_analysis(self, instrs):
     """
     Reconstruct symbolic information
     :param instrs: instruction list
     :return: instruction list with labels
     """
     func = lambda i: self.check_text(get_loc(i).loc_addr)
     self.instr_list = instrs
     if ELF_utils.elf_arm():
         self.pcreloffARM(instrs)
         instrs = map(self.vinst2ARM, enumerate(instrs))
         self.doublemovARM(instrs)
     else:
         instrs = map(lambda i: self.vinst2(func, i), instrs)
     self.symbol_list = map(lambda l: int(l.split('x')[1], 16),
                            self.deslist) + self.symbol_list
     return instrs
Ejemplo n.º 18
0
def pp_print_instr(i):
    """
    Get instruction string in assembler syntax
    :param i: instruction
    :return: instruction string
    """
    loc = get_loc(i)
    if not loc.loc_visible: return p_location(loc)
    res = p_location(loc) + p_prefix(i[-1])
    if isinstance(i, Types.SingleInstr):
        res += p_single(i[0])
    elif isinstance(i, Types.DoubleInstr):
        res += p_double(i[0], i[1])
    elif isinstance(i, Types.TripleInstr):
        res += p_triple(i[0], i[1], i[2])
    elif isinstance(i, Types.FourInstr):
        res += p_four(i[0], i[1], i[2], i[3])
    elif isinstance(i, Types.FiveInstr):
        res += p_five(i[0], i[1], i[2], i[3], i[4])
    elif ELF_utils.elf_arm() and isinstance(i, Types.CoproInstr):
        res += p_copro(i)
    return res
Ejemplo n.º 19
0
 def addxorcanary(self, i, func):
     """
     Apply return address encryption
     :param i: starting instruction index
     :param func: current funtion
     :return: instruction index after last inserted block
     """
     if func.func_begin_addr in self.avoid: return i + 1
     if len(self.indcalls[func.func_begin_addr]) == 0:
         header = inlining.get_returnenc(self.instrs[i])
         self.instrs[i:i + 1] = header
         i += len(header) - 1
         popcookie = False
     else:
         popcookie = True
     for t in self.rets[func.func_begin_addr]:
         while get_loc(self.instrs[i]).loc_addr != t:
             i += 1
         if ELF_utils.elf_arm(
         ) and self.instrs[i][0][-2:] in Types.CondSuff:
             # Handle somehow IT blocks
             itlen = 0
             while not self.instrs[i - itlen][0].upper().startswith(
                     'IT') and itlen < 5:
                 itlen += 1
             if itlen < 5:
                 i -= itlen
                 j = len(self.instrs[i][0].strip()) + 1
                 self.instrs[i:i + j] = inlining.translate_it_block(
                     self.instrs[i:i + j])
                 while get_loc(self.instrs[i]).loc_addr != t:
                     i += 1
         footer = inlining.get_returnenc(self.instrs[i], popcookie)
         self.instrs[i:i + 1] = footer
         i += len(footer)
     return i
Ejemplo n.º 20
0
cmpb $0,{1}
jne .{0}.L1
movl $.LC1,%edi
movl $49,%edx
jmp .{0}.L2
.{0}.L1: movl $.LC0,%edi
movl $18,%edx
.{0}.L2: movl $1,%esi
call fwrite
movl $-1,%edi
call exit


'''

elif ELF_utils.elf_arm():
    # ARM
    keygenfunction = '''
push {{r0,r1,r2,r4,r12,lr}}
movw r0,#:lower16:.LC2
movt r0,#:upper16:.LC2
movs r1,#0
bl open
subs r4,r0,#0
blt {0}
movs r2,#4
movw r1,#:lower16:{1}
movt r1,#:upper16:{1}
bl read
cmp r0,#4
mov r2,r0
Ejemplo n.º 21
0
    :param assist: assist operator
    :return: lowercase assist operator
    """
    return str(assist).lower()


def p_loc(loc):
    """
    String of location address
    :param loc: location address
    :return: lowercase hexdecimal string
    """
    return '0x%x' % loc


if ELF_utils.elf_arm():
    ## ARM

    def p_reg(reg):
        """
        String of register
        :param reg: register
        :return: lowercase register string
        """
        return str(reg).lower()

    def p_shift(shift):
        """
        String of shift operand
        :param shift: shift value
        :return: shift operand string
Ejemplo n.º 22
0
 def v_exp2(self, exp, instr, f, chk):
     """
     Analyze expression and determine if it represent an address.
     If so substitute if with a corresponding symbolic expression using labels
     :param exp: expression
     :param instr: instruction tuple to which the expression belongs to
     :param f: unused
     :param chk: True if instruction is TEST (x86)
     :return: modified expression if matching, original one otherwise
     """
     if isinstance(exp, Types.Const):
         if isinstance(exp, Types.Normal) and chk: return exp
         s = self.check_sec(exp)
         if s is not None:
             self.insert_data(s.sec_name, exp)
             return Types.Label(self.build_symbol(exp))
         if self.check_text(exp):
             if ELF_utils.elf_arm(): exp = type(exp)(exp & (-2))
             s_label = self.build_symbol(exp)
             self.insert_text(s_label, exp)
             return Types.Label(s_label)
         if self.check_plt(exp):
             return Types.Label(self.build_plt_symbol(exp))
     elif isinstance(exp, Types.Symbol):
         if isinstance(exp, Types.JumpDes):
             if self.check_text(exp):
                 s_label = 'S_' + dec_hex(exp)
                 self.insert_text(s_label, exp)
                 return Types.Label(s_label)
             elif self.check_plt(exp) and exp in self.plt_hash:
                 return Types.Label(self.plt_hash[exp])
         elif isinstance(exp, Types.StarDes):
             return Types.StarDes(self.v_exp2(exp.content, instr, f, chk))
         elif isinstance(exp, Types.CallDes):
             if exp.func_name.startswith('S_0'):
                 addr = int(exp.func_name[2:], 16)
                 if self.check_text(addr):
                     s_label = 'S_' + dec_hex(addr)
                     self.insert_text(s_label, addr)
                     return Types.Label(s_label)
                 elif self.check_plt(addr):
                     off = 0
                     while not self.plt_hash.get(addr - off, None):
                         off += 2
                     return Types.Label(self.plt_hash[addr - off])
             else:
                 self.symbol_list.insert(0, exp.func_begin_addr)
     elif isinstance(exp, Types.Ptr):
         if isinstance(exp, (Types.BinOP_PLUS, Types.BinOP_MINUS)):
             r, addr = exp
             s = self.check_sec(addr)
             if s is not None:
                 s_label = 'S_' + dec_hex(addr)
                 self.insert_data(s.sec_name, addr)
                 return Types.BinOP_PLUS_S((r, s_label)) \
                     if isinstance(exp, Types.BinOP_PLUS) \
                     else Types.BinOP_MINUS_S((r, s_label))
         elif isinstance(exp, (Types.FourOP_PLUS, Types.FourOP_MINUS)):
             r1, r2, off, addr = exp
             s = self.check_sec(addr)
             if s is not None:
                 s_label = 'S_' + dec_hex(addr)
                 self.insert_data(s.sec_name, addr)
                 return Types.FourOP_PLUS_S((r1,r2,off,s_label)) \
                     if isinstance(exp, Types.FourOP_PLUS) \
                     else Types.FourOP_MINUS_S((r1,r2,off,s_label))
         elif isinstance(exp, Types.JmpTable_PLUS):
             addr, r, off = exp
             s = self.check_sec(addr)
             if s is not None:
                 s_label = 'S_' + dec_hex(addr)
                 self.insert_data(s.sec_name, addr)
                 return Types.JmpTable_PLUS_S((s_label, r, off))
             if self.check_text(addr):
                 s_label = 'S_' + dec_hex(addr)
                 self.insert_text(s_label, addr)
                 return Types.JmpTable_PLUS_S((s_label, r, off))
         elif isinstance(exp, Types.JmpTable_MINUS):
             addr, r, off = exp
             s = self.check_sec(addr)
             if s is not None:
                 s_label = '-S_' + dec_hex(addr)
                 self.insert_data(s.sec_name, addr)
                 return Types.JmpTable_MINUS_S((s_label, r, off))
             if self.check_text(addr):
                 s_label = '-S_' + dec_hex(addr)
                 self.insert_text(s_label, addr)
                 return Types.JmpTable_MINUS_S((s_label, r, off))
     return exp