Esempio n. 1
0
    def disassemble(code, offset=0x0):  # pylint: disable=arguments-differ
        with utils.tempdir() as td:
            bin_fname = os.path.join(td, "code.bin")

            fp = open(bin_fname, 'wb')
            fp.write(code)
            fp.close()
            res = utils.exec_cmd(
                "avr-objdump -D -b binary -m avr5 %s | tail +8" % (bin_fname),
                shell=True)
            if res[2] != 0:
                raise Exception("avr-objdump error: " +
                                str(res[0] + res[1], 'utf-8'))
            str_result = res[0].decode("utf-8")

        result = []
        for line in str_result.splitlines():
            m = re.match(
                r"\s+(?P<address>[0-9a-f]+):\s+(?P<bytes>([0-9a-f]{2}\s)+)\s+(?P<mnemonic>.+?)\s+(?P<op_str>.+?)$",
                line)
            if m:
                instr = AttrDict(m.groupdict())
                instr['address'] = int(instr['address'], 16) + offset
                instr['bytes'] = bytes.fromhex(instr['bytes'])
                instr['mnemonic'] = re.sub(r'\s+', '', instr['mnemonic'])
                instr['op_str'] = re.sub(
                    r'\s+', '',
                    instr['op_str'].split(";")[0]).replace(",", ", ")
                result.append(instr)
        return result
Esempio n. 2
0
    def compile_function(code,
                         compiler_flags="-fPIE",
                         bits=32,
                         little_endian=False,
                         entry=0x0,
                         symbols=None):
        with utils.tempdir() as td:
            c_fname = os.path.join(td, "code.c")
            object_fname = os.path.join(td, "code.o")
            object2_fname = os.path.join(td, "code.2.o")
            linker_script_fname = os.path.join(td, "code.lds")

            with open(c_fname, 'w') as fp:
                fp.write(code)

            linker_script = "SECTIONS { .text : { *(.text) "
            if symbols:
                for i in symbols:
                    linker_script += i + " = " + hex(symbols[i] - entry) + ";"
            linker_script += "}}"

            with open(linker_script_fname, 'w') as fp:
                fp.write(linker_script)

            target = ("mipsel-linux-gnu" if little_endian else
                      "mips-linux-gnu") if bits == 32 else (
                          "mips64el-linux-gnuabi64"
                          if little_endian else "mips64-linux-gnuabi64")
            res = utils.exec_cmd("clang -target %s -o %s -c %s %s" \
                            % (target, object_fname, c_fname, compiler_flags), shell=True)
            if res[2] != 0:
                raise CLangException("CLang error: " +
                                     str(res[0] + res[1], 'utf-8'))

            res = utils.exec_cmd(
                "ld.lld -relocatable %s -T %s -o %s" %
                (object_fname, linker_script_fname, object2_fname),
                shell=True)
            if res[2] != 0:
                raise Exception("Linking Error: " +
                                str(res[0] + res[1], 'utf-8'))
            ld = cle.Loader(object2_fname, main_opts={"base_addr": 0x0})

            compiled = ld.memory.load(ld.all_objects[0].entry,
                                      0xFFFFFFFFFFFFFFFF)
        return compiled
Esempio n. 3
0
    def compile_function(code, compiler_flags="", entry=0x0, symbols=None):
        with utils.tempdir() as td:
            c_fname = os.path.join(td, "code.c")
            object_fname = os.path.join(td, "code.o")
            object2_fname = os.path.join(td, "code.2.o")
            linker_script_fname = os.path.join(td, "code.lds")

            # C -> Object File
            with open(c_fname, 'w') as fp:
                fp.write(code)
            # clang -target avr -mmcu=atmega328p
            res = utils.exec_cmd("avr-gcc -mmcu=atmega328p -o %s -c %s %s" %
                                 (object_fname, c_fname, compiler_flags),
                                 shell=True)
            if res[2] != 0:
                raise Exception("avr-gcc error: " +
                                str(res[0] + res[1], 'utf-8'))

            # Setup Linker Script
            linker_script = "SECTIONS { .text : { *(.text) "
            if symbols:
                for i in symbols:
                    linker_script += i + " = " + hex(symbols[i] - entry) + ";"
            linker_script += "}}"

            with open(linker_script_fname, 'w') as fp:
                fp.write(linker_script)

            # Object File --LinkerScript--> Object File
            res = utils.exec_cmd(
                "avr-ld -relocatable %s -T %s -o %s" %
                (object_fname, linker_script_fname, object2_fname),
                shell=True)
            if res[2] != 0:
                raise Exception("Linking Error: " +
                                str(res[0] + res[1], 'utf-8'))

            ld = cle.Loader(object2_fname, main_opts={"base_addr": 0x0})
            compiled = ld.memory.load(ld.all_objects[0].entry,
                                      0xFFFFFFFFFFFFFFFF)
        return compiled
Esempio n. 4
0
    def compile_function(code,
                         compiler_flags="",
                         is_thumb=False,
                         entry=0x0,
                         symbols=None):
        with utils.tempdir() as td:
            c_fname = os.path.join(td, "code.c")
            object_fname = os.path.join(td, "code.o")
            object2_fname = os.path.join(td, "code.2.o")
            linker_script_fname = os.path.join(td, "code.lds")

            with open(c_fname, 'w') as fp:
                fp.write(code)

            linker_script = "SECTIONS { .text : { *(.text) "
            if symbols:
                for i in symbols:
                    linker_script += i + " = " + hex(symbols[i] - entry) + ";"
            linker_script += "}}"

            with open(linker_script_fname, 'w') as fp:
                fp.write(linker_script)

            res = utils.exec_cmd("clang -target arm-none-eabi -Os -mcpu=cortex-m0 -o %s -c %s %s %s" \
                            % (object_fname, c_fname, compiler_flags, "-mthumb" if is_thumb else "-mno-thumb"), shell=True)
            if res[2] != 0:
                raise CLangException("CLang error: " +
                                     str(res[0] + res[1], 'utf-8'))

            res = utils.exec_cmd(
                "ld.lld -relocatable %s -T %s -o %s" %
                (object_fname, linker_script_fname, object2_fname),
                shell=True)
            if res[2] != 0:
                raise Exception("Linking Error: " +
                                str(res[0] + res[1], 'utf-8'))

            ld = cle.Loader(object2_fname, main_opts={"base_addr": 0x0})
            compiled = ld.memory.load(ld.all_objects[0].entry,
                                      0xFFFFFFFFFFFFFFFF)
        return compiled
Esempio n. 5
0
    def compile_asm(code, name_map=None):  # pylint: disable=arguments-differ
        if not code.endswith("\n"):  # prevent avr-as warning
            code += "\n"
        try:
            if name_map is not None:
                code = code.format(**name_map)  # compile_asm
            else:
                code = re.subn(r'{.*?}', "0x41414141",
                               code)[0]  # solve symbols # TODO
        except KeyError as e:
            raise UndefinedSymbolException(str(e)) from e

        with utils.tempdir() as td:
            asm_fname = os.path.join(td, "code.asm")
            object_fname = os.path.join(td, "code.o")
            bin_fname = os.path.join(td, "code.bin")

            fp = open(asm_fname, 'w')
            fp.write(code)
            fp.close()

            res = utils.exec_cmd("avr-as -mmcu=avr5 %s -o %s" %
                                 (asm_fname, object_fname),
                                 shell=True)
            if res[2] != 0:
                raise Exception("avr-as error: " +
                                str(res[0] + res[1], 'utf-8'))

            res = utils.exec_cmd("objcopy -B i386 -O binary -j .text %s %s" %
                                 (object_fname, bin_fname),
                                 shell=True)
            if res[2] != 0:
                raise Exception("objcopy error: " +
                                str(res[0] + res[1], 'utf-8'))

            fp = open(bin_fname, "rb")
            compiled = fp.read()
            fp.close()
        return compiled
Esempio n. 6
0
    def compile_c(self, code, optimization='-Oz', compiler_flags=""):
        # TODO symbol support in c code
        with utils.tempdir() as td:
            c_fname = os.path.join(td, "code.c")
            object_fname = os.path.join(td, "code.o")
            bin_fname = os.path.join(td, "code.bin")

            fp = open(c_fname, 'w')
            fp.write(code)
            fp.close()
            print(self.project.arch.triplet)
            res = utils.exec_cmd("clang -nostdlib -mno-sse -target %s -ffreestanding %s -o %s -c %s %s" \
                            % (self.project.arch.triplet, optimization, object_fname, c_fname, compiler_flags), shell=True)
            if res[2] != 0:
                print("CLang error:")
                print(res[0])
                print(res[1])
                fp = open(c_fname, 'r')
                fcontent = fp.read()
                fp.close()
                print("\n".join([
                    "%02d\t%s" % (i + 1, j)
                    for i, j in enumerate(fcontent.split("\n"))
                ]))
                raise CLangException
            res = utils.exec_cmd("objcopy -B i386 -O binary -j .text %s %s" %
                                 (object_fname, bin_fname),
                                 shell=True)
            if res[2] != 0:
                print("objcopy error:")
                print(res[0])
                print(res[1])
                raise ObjcopyException
            fp = open(bin_fname, "rb")
            compiled = fp.read()
            fp.close()
        return compiled
Esempio n. 7
0
    def compile_function(code,
                         compiler_flags="",
                         bits=32,
                         little_endian=False,
                         entry=0x0,
                         symbols=None,
                         data_only=False,
                         prefix=""):
        with utils.tempdir() as td:
            c_fname = os.path.join(td, "code.c")
            object_fname = os.path.join(td, "code.o")
            object2_fname = os.path.join(td, "code.2.o")
            linker_script_fname = os.path.join(td, "code.lds")
            data_fname = os.path.join(td, "data")
            rodata_sec_index = rodata_sym_index_old = rodata_sym_index_new = -1

            # C -> Object File
            with open(c_fname, 'w') as fp:
                fp.write(code)
            target = ("powerpcle-linux-gnu" if little_endian else
                      "powerpc-linux-gnu") if bits == 32 else (
                          "powerpc64le-linux-gnu"
                          if little_endian else "powerpc64-linux-gnu")
            res = utils.exec_cmd("clang -target %s -o %s -c %s %s" \
                            % (target, object_fname, c_fname, compiler_flags), shell=True)
            if res[2] != 0:
                raise CLangException("CLang error: " +
                                     str(res[0] + res[1], 'utf-8'))

            # Setup Linker Script
            linker_script = "SECTIONS { .text : { *(.text) "
            if symbols:
                for i in symbols:
                    if i == ".rodata":
                        linker_script += i + " = " + hex(symbols[i] - (
                            (entry - 0x10700000) & ~0xFFFF)) + ";"
                    else:
                        linker_script += i + " = " + hex(symbols[i] -
                                                         entry) + ";"
            linker_script += "} .rodata : { *(.rodata*) } }"
            with open(linker_script_fname, 'w') as fp:
                fp.write(linker_script)

            # Object File --LinkerScript--> Object File
            res = utils.exec_cmd(
                "ld.lld -relocatable %s -T %s -o %s" %
                (object_fname, linker_script_fname, object2_fname),
                shell=True)
            if res[2] != 0:
                raise Exception("Linking Error: " +
                                str(res[0] + res[1], 'utf-8'))

            # Load Object File
            ld = cle.Loader(object2_fname,
                            main_opts={"base_addr": 0x0},
                            perform_relocations=False)

            # Figure Out .text Section Size
            for section in ld.all_objects[0].sections:
                if section.name == ".text":
                    text_section_size = section.filesize
                    break

            # Modify Symbols in Object File to Trick Loader
            with open(object2_fname, "rb+") as f:
                elf = ELFFile(f)

                # Find the Index of .rodata Section
                for i in range(elf.num_sections()):
                    if elf.get_section(i).name == ".rodata":
                        rodata_sec_index = i
                        break

                # Find the Index of the src and dest Symbol
                symtab_section = elf.get_section_by_name(".symtab")
                for i in range(symtab_section.num_symbols()):
                    if symtab_section.get_symbol(
                            i
                    )['st_shndx'] == rodata_sec_index and symtab_section.get_symbol(
                            i)['st_info']['type'] == 'STT_SECTION':
                        rodata_sym_index_old = i
                    if symtab_section.get_symbol(i).name == ".rodata":
                        rodata_sym_index_new = i

                # Rewrite the Symbol
                if rodata_sym_index_new != -1 and rodata_sec_index != -1 and rodata_sym_index_old != -1:
                    for i in range(elf.num_sections()):
                        if elf.get_section(i).header[
                                'sh_name'] == symtab_section.header['sh_name']:
                            f.seek(0)
                            content = f.read()
                            f.seek(symtab_section['sh_offset'] +
                                   rodata_sym_index_new *
                                   symtab_section['sh_entsize'])
                            rodata_sym_new = f.read(
                                symtab_section['sh_entsize'])
                            content = utils.bytes_overwrite(
                                content, rodata_sym_new,
                                symtab_section['sh_offset'] +
                                rodata_sym_index_old *
                                symtab_section['sh_entsize'])
                            f.seek(0)
                            f.write(content)
                            f.truncate()
                            break

                # Replace all R_PPC_PLTREL24 to R_PPC_REL24
                rela_section = elf.get_section_by_name(".rela.text")
                if rela_section is not None:
                    for i in range(rela_section.num_relocations()):
                        if rela_section.get_relocation(i)['r_info_type'] == 18:
                            reloc = rela_section.get_relocation(i).entry
                            reloc['r_info'] -= 8

                            for j in range(elf.num_sections()):
                                if elf.get_section(j).header[
                                        'sh_name'] == rela_section.header[
                                            'sh_name']:
                                    f.seek(0)
                                    content = f.read()
                                    content = utils.bytes_overwrite(
                                        content,
                                        elf.structs.Elf_Rela.build(reloc),
                                        rela_section['sh_offset'] +
                                        i * rela_section['sh_entsize'])
                                    f.seek(0)
                                    f.write(content)
                                    f.truncate()
                                    break

            # Load the Modified Object File and Return compiled Data or Code
            ld = cle.Loader(object2_fname,
                            main_opts={
                                "base_addr": 0x0,
                                "entry_point": 0x0
                            })
            if data_only:
                patches = []
                for section in ld.all_objects[0].sections:
                    if section.name == ".rodata":
                        res = utils.exec_cmd(
                            "objcopy -B i386 -O binary -j %s %s %s" %
                            (section.name, object2_fname, data_fname),
                            shell=True)
                        if res[2] != 0:
                            raise ObjcopyException("Objcopy Error: " +
                                                   str(res[0] +
                                                       res[1], 'utf-8'))
                        with open(data_fname, "rb") as fp:
                            patches.append(
                                AddRODataPatch(fp.read(),
                                               name=prefix + section.name))
                        break
                return patches
            else:
                compiled = ld.memory.load(ld.all_objects[0].entry,
                                          text_section_size)
                return compiled
Esempio n. 8
0
    def compile_function(self,
                         code,
                         compiler_flags="",
                         is_thumb=False,
                         entry=0x0,
                         symbols=None):
        with utils.tempdir() as td:
            c_fname = os.path.join(td, "code.c")
            object_fname = os.path.join(td, "code.o")
            object2_fname = os.path.join(td, "code.2.o")
            linker_script_fname = os.path.join(td, "code.lds")

            with open(c_fname, 'w') as fp:
                fp.write(code)

            linker_script = "SECTIONS { .text : SUBALIGN(0) { . = " + hex(
                entry) + "; *(.text) "
            if symbols:
                for i in symbols:
                    linker_script += i + " = " + hex(symbols[i]) + ";"
            linker_script += "}}"

            with open(linker_script_fname, 'w') as fp:
                fp.write(linker_script)

            res = utils.exec_cmd("clang -target arm-linux-gnueabihf -o %s -c %s %s %s" \
                            % (object_fname, c_fname, compiler_flags, "-mthumb" if is_thumb else "-mno-thumb"), shell=True)
            if res[2] != 0:
                raise CLangException("CLang error: " +
                                     str(res[0] + res[1], 'utf-8'))

            res = utils.exec_cmd(
                "ld.lld -relocatable %s -T %s -o %s" %
                (object_fname, linker_script_fname, object2_fname),
                shell=True)
            if res[2] != 0:
                raise Exception("Linking Error: " +
                                str(res[0] + res[1], 'utf-8'))

            ld = cle.Loader(object2_fname, main_opts={"base_addr": 0x0})
            compiled = ld.memory.load(ld.all_objects[0].entry + entry,
                                      ld.memory.max_addr)

            disasm = self.disassemble(compiled, entry, is_thumb=is_thumb)
            disasm_str = ""
            for instr in disasm:
                if is_thumb and instr.mnemonic == "bl" and instr.operands[
                        0].imm in symbols.values():
                    disasm_str += self.capstone_to_asm(instr).replace(
                        "bl", "blx") + "\n"
                elif is_thumb and instr.mnemonic == "blx" and (
                        instr.operands[0].imm + 1) in symbols.values():
                    disasm_str += self.capstone_to_asm(instr).replace(
                        "blx", "bl") + "\n"
                elif not is_thumb and instr.mnemonic == "bl" and (
                        instr.operands[0].imm + 1) in symbols.values():
                    disasm_str += self.capstone_to_asm(instr).replace(
                        "bl", "blx") + "\n"
                elif not is_thumb and instr.mnemonic == "blx" and instr.operands[
                        0].imm in symbols.values():
                    disasm_str += self.capstone_to_asm(instr).replace(
                        "blx", "bl") + "\n"
                else:
                    disasm_str += self.capstone_to_asm(instr) + "\n"
            compiled = self.compile_asm(disasm_str,
                                        base=entry,
                                        name_map={},
                                        is_thumb=is_thumb)
        return compiled
Esempio n. 9
0
    def compile_function(self,
                         code,
                         compiler_flags="",
                         bits=32,
                         entry=0x0,
                         symbols=None,
                         stacklayout=None):
        import json
        with utils.tempdir() as td:
            c_fname = os.path.join(td, "code.c")
            ll_fname = os.path.join(td, "code.ll")
            ll2_fname = os.path.join(td, "code.2.ll")
            json_fname = os.path.join(td, "code.json")
            object_fname = os.path.join(td, "code.o")
            object2_fname = os.path.join(td, "code.2.o")
            linker_script_fname = os.path.join(td, "code.lds")

            if stacklayout is None:
                clang = "clang-11"
                opt = "opt-11"
                llc = "llc-11"
                lld = "ld.lld-11"
            else:
                clang = "/precompiled_llvm_bins/clang"
                opt = "/precompiled_llvm_bins/opt"
                llc = "/precompiled_llvm_bins/llc"
                lld = "/precompiled_llvm_bins/ld.lld"

            with open(c_fname, 'w') as fp:
                fp.write(code)

            linker_script = "SECTIONS { .text : SUBALIGN(0) { . = " + hex(
                entry) + "; *(.text) "
            if symbols is not None:
                for i in symbols:
                    linker_script += i + " = " + hex(symbols[i]) + ";"
            linker_script += "}}"
            print(linker_script)
            with open(linker_script_fname, 'w') as fp:
                fp.write(linker_script)

            # c -> ll
            res = utils.exec_cmd(
                "%s -S -emit-llvm -g -o %s %s %s %s" %
                (clang, ll_fname, "-m32" if bits == 32 else "-m64", c_fname,
                 compiler_flags),
                shell=True)
            if res[2] != 0:
                raise Exception("Clang Error: " +
                                str(res[0] + res[1], 'utf-8'))

            # ll --force-dso-local-> ll
            res = utils.exec_cmd(
                "%s -load /precompiled_llvm_bins/LLVMAMP.so --force-dso-local -S %s -o %s"
                % (opt, ll_fname, ll_fname),
                shell=True)
            if res[2] != 0:
                raise Exception("opt Error: " + str(res[0] + res[1], 'utf-8'))

            res = utils.exec_cmd("%s -Os -S %s -o %s" %
                                 (opt, ll_fname, ll_fname),
                                 shell=True)
            if res[2] != 0:
                raise Exception("opt Error: " + str(res[0] + res[1], 'utf-8'))

            # # ll -> ll + AMPDebug
            if stacklayout is not None:
                self.addAMPDebug(ll_fname, ll2_fname, stacklayout)
            else:
                ll2_fname = ll_fname

            # ll + AMPDebug -> obj
            res = utils.exec_cmd(
                "%s -o %s %s -relocation-model=pic --x86-asm-syntax=intel --filetype=obj"
                % (llc, object_fname, ll2_fname),
                shell=True)
            if res[2] != 0:
                raise CLangException("llc error: " +
                                     str(res[0] + res[1], 'utf-8'))
            print(str(res[1], 'utf-8'))  # TODO: remove this

            # relocate
            res = utils.exec_cmd(
                "%s -relocatable %s -T %s -o %s" %
                (lld, object_fname, linker_script_fname, object2_fname),
                shell=True)
            if res[2] != 0:
                raise Exception("Linking Error: " +
                                str(res[0] + res[1], 'utf-8'))
            print(str(res[1], 'utf-8'))

            ld = cle.Loader(object2_fname, main_opts={"base_addr": 0x0})
            compiled = ld.memory.load(ld.all_objects[0].entry + entry,
                                      ld.memory.max_addr)
        return compiled