Example #1
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
Example #2
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
Example #3
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
Example #4
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
Example #5
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