Beispiel #1
0
def Assemble(ea, line):
    """
    Assembles one or more lines (does not display an message dialogs)
    If line is a list then this function will attempt to assemble all the lines
    This function will turn on batch mode temporarily so that no messages are displayed on the screen

    @param ea:       start address
    @return: (False, "Error message") or (True, asm_buf) or (True, [asm_buf1, asm_buf2, asm_buf3])
    """
    old_batch = idc.Batch(1)
    ret = _Assemble(ea, line)
    idc.Batch(old_batch)
    return ret
Beispiel #2
0
def SimpleAsm(string):

    if sys.modules.has_key('miasm'):
        try:
            i_opcode = x86_mn.asm(string.lower())
        except:
            print ">Assembler:SimpleAsm - Error miasm.asm() for [%s]" % string
            i_opcode = ''

        if len(i_opcode) > 0:
            return i_opcode

    idc.Batch(1)

    while True:
        seg_start = random.randint(0x1000, 0xffffffff)
        seg_size = 0x20
        if idc.SegCreate(seg_start, seg_start + seg_size, 0, 1, 0, 0) != 0:
            break

    tmp = idaapi.assemble(seg_start, 0, seg_start, 1, string)

    if tmp == 0:
        while idc.SegDelete(seg_start, 0) != 0:
            pass
        idc.Batch(0)
        print "Failed to assemble [%s]" % string
        raise MiscError

    idc.MakeCode(seg_start)

    opcode = ''.join([
        chr(idc.Byte(seg_start + i))
        for i in xrange(0,
                        idc.ItemSize(seg_start) - 1)
    ])

    while idc.SegDelete(seg_start, 0) != 0:
        pass

    idc.Batch(0)
    return opcode
Beispiel #3
0
def batch(num):
    if idaapi.IDA_SDK_VERSION <= 699:
        idc.Batch(num)
    else:
        idc.batch(num)
Beispiel #4
0
    def Assemble(self, function, nasm=True):
        '''
            Main Assemble Function
        '''

        if self.functions.has_key(function.start_ea):
            ans = idaapi.askyn_c(
                1,
                "HIDECANCEL\nFunction @ [%08x] was already optimized, are you sure you want to overwrite old one?"
            )
            if ans == 0:
                return

        idc.Batch(1)

        self.jmp_table = ""
        self.jmp_table_refs = []
        self.jmp_deps = {}
        self.ref_instr = {}
        self.bb_head_ea = {}

        function_ea = self.free_ea
        function_end = None

        if debug:
            print ">Assemble(%08x) - Starting" % function.start_ea

        if nasm:
            if self.opty_dir == None:
                self.opty_dir = idc.GetIdbPath()
                self.opty_dir = self.opty_dir[:self.opty_dir.rfind(
                    os.sep)] + os.sep + "optimice_%s" % idc.GetInputFile()
                if not os.path.isdir(self.opty_dir):
                    os.mkdir(self.opty_dir)

            self.nasm = True
            self.nasmfw = open(
                self.opty_dir + os.sep + 'f_%08x.asm' % function.start_ea,
                "w+")
            self.NasmWriteToFile("[BITS 32]\n")
            self.NasmWriteToFile("\torg %09xh\n" % function_ea)
        else:
            self.nasm = False

        for bb_ea in function.DFSFalseTraverseBlocks():
            if self.nasm:
                self.NasmWriteToFile("\nL%08x:\n" % bb_ea)
                self.bb_head_ea[bb_ea] = True
            else:
                self.bb_head_ea[bb_ea] = self.free_ea

            for instr in function.GetBBInstructions(bb_ea):
                if instr == None:
                    continue

                mnem = self.BuildAsmString(instr, function)

                if debug:
                    print ">Assemble - Assembling @ %08x [%s]" % (
                        instr.GetOriginEA(), mnem)

                if not self.nasm:
                    self.AsmAndWrite(mnem, instr, function=function)

            if not instr.IsCFI():
                ref_from = list(function.GetRefsFrom(
                    instr.GetOriginEA()))[0][0]

                if self.bb_head_ea.has_key(ref_from):
                    if self.nasm:
                        self.NasmWriteToFile("\tjmp L%08x ; \n" % ref_from)
                    else:
                        self.AsmAndWrite("jmp %09xh" %
                                         self.bb_head_ea[ref_from])

            elif instr.GetMnem() == "call":
                for ref, path in function.GetRefsFrom(instr.GetOriginEA()):
                    if path == False:
                        if self.bb_head_ea.has_key(ref):
                            if self.nasm:
                                self.NasmWriteToFile(
                                    "\tjmp L%08x ; ###FAKE 2 JMP###\n" % ref)
                            else:
                                self.AsmAndWrite("jmp %09xh" %
                                                 self.bb_head_ea[ref])

            elif instr.IsJcc():
                ref_from = list(function.GetRefsFrom(instr.GetOriginEA()))
                for ref, path in ref_from:
                    if path == False:
                        break

                if path == True:
                    raise MiscError

                elif self.bb_head_ea.has_key(ref):
                    print "Check this out @ [%08x] ref:[%08x]" % (
                        instr.GetOriginEA(), ref)
                    if self.nasm:
                        self.NasmWriteToFile(
                            "\tjmp L%08x ; ###FAKE 2 JMP###\n" % ref)
                    else:
                        self.AsmAndWrite("jmp %09xh" % self.bb_head_ea[ref])

        ret = None
        if self.nasm:
            self.NasmWriteToFile(self.jmp_table)

            self.nasmfw.close()
            self.nasmfw = None

            ret = self.NasmAssemble(function.start_ea, self.free_ea)
            if ret != None:
                self.free_ea = ret
        else:
            ret = self.AsmAndWriteBranches(function)
            self.free_ea = ret

        self.ref_instr = {}
        idc.Batch(0)

        if ret != None:
            idc.MakeFunction(function_ea)

            comment = idc.Comment(function_ea)
            if comment != None:
                comment = 'Origin@[%08x]; %s' % (function.start_ea, comment)
            else:
                comment = 'Origin@[%08x];' % function.start_ea

            idc.MakeComm(function_ea, comment)

            comment = idc.Comment(function.start_ea)
            if comment != None:
                comment = 'OPTY@[%08x]; %s' % (function_ea, comment)
            else:
                comment = 'OPTY@[%08x];' % function_ea

            idc.MakeComm(function.start_ea, comment)

            idaapi.set_name(function_ea, "om_%s" % idc.Name(function.start_ea))

        function_end = self.free_ea
        self.functions[function.start_ea] = (function_ea, function_end)

        idaapi.refresh_idaview_anyway()
Beispiel #5
0
    def NasmAssemble(self, function_ea, write_ea):
        dir = self.opty_dir

        nasm = "C:\\Program Files\\nasm\\nasm.exe"
        arg1 = "f_%08x.asm" % function_ea
        arg2 = "-o f_%08x.o" % function_ea
        arg3 = "-l f_%08x.lst" % function_ea
        arg4 = "-Ox"

        orig_dir = os.getcwd()
        os.chdir(dir)

        idc.Batch(0)
        while 1:
            try:
                p = subprocess.Popen([nasm, arg1, arg2, arg3, arg4],
                                     stdout=subprocess.PIPE,
                                     stderr=subprocess.PIPE,
                                     stdin=subprocess.PIPE)
                o, e = p.communicate()

                if o != "": print o
                if e != "": print e

                fop = open("f_%08x.o" % function_ea, "rb")

                ans = idaapi.askyn_c(
                    0,
                    "HIDECANCEL\nDo you want to manually edit function before writing to IDA?"
                )
                if ans == 1:
                    os.startfile(arg1, "open")
                    idaapi.warning(
                        "Press OK button when you're done editing file.")
                    fop.close()
                    continue
                else:
                    idc.Batch(1)
                    break

            except:
                error_msg = '\n'.join(e.split("\n")[:15])

                os.startfile(arg1, "open")
                ans = idaapi.askyn_c(
                    1, """HIDECANCEL\nNASM failed to assemble [f_%08x.o] file.
You can manually edit and NASM this file [f_%08x.asm] and click Yes when you're done.
File is located in directory where your IDB is located.
If you want to skip this function press No.

Nasm output:
%s""" % (function_ea, function_ea, error_msg))

                if ans == 1:
                    continue
                else:
                    os.chdir(orig_dir)
                    idc.Batch(1)
                    return None

        os.chdir(orig_dir)

        print ">>>Writing function [%08x] @ [%08x]" % (function_ea, write_ea)

        data = fop.read()
        data_len = len(data)
        for offset in xrange(0, data_len):
            idc.PatchByte(write_ea + offset, ord(data[offset]))
        fop.close()

        idc.MakeCode(write_ea)

        fp = open("%s\\f_%08x.lst" % (dir, function_ea), "r")
        asm_lst = fp.read()

        base_addr = re.search(r"ORG ([\dABCDEF]+)H", asm_lst).group(1)
        base_addr = int(base_addr, 16)

        for jt in self.jmp_table_refs:
            m = re.search(r"\s*\d+\s+([\dABCDEF]{8}).*?%s" % re.escape(jt),
                          asm_lst, re.IGNORECASE)
            if m != None:
                jt_ea = int(m.group(1), 16)
                jt_str = re.search(r"SJ_.{8}", jt, re.IGNORECASE).group()
                for m in re.findall(
                        r"(?i)\n\s*\d+\s+[\dABCDEF]{8}\s+.*?\s+%s" %
                        re.escape(jt_str), asm_lst):
                    r = re.search(r"\d+\s([\dABCDEF]{8})", m.strip(),
                                  re.IGNORECASE).group(1)

                    #print "AddCodeXref(0x%08x, 0x%08x, idc.XREF_USER)" % (jt_ea+base_addr, idc.Dword(int(r, 16)+base_addr))
                    idc.AddCodeXref(jt_ea + base_addr,
                                    idc.Dword(int(r, 16) + base_addr),
                                    idc.XREF_USER)
            else:
                raise MiscError

        for line in asm_lst.split("\n"):
            comment = re.search(r"###(.*?)###", line)
            if comment != None:
                data = re.search(r"\s*\d+\s([\dABCDEF]+)\s([\dABCDEF\(\)]+)",
                                 line)
                if data != None:
                    offset = int(data.group(1), 16)
                    idc.MakeComm(write_ea + offset, comment.group(1))

        fp.close()

        return write_ea + data_len + 10