Пример #1
0
    def test_se_1(self):
        binary = BinaryFile(get_full_path("/data/bin/check_serial_1"))

        arch_info = X86ArchitectureInformation(binary.architecture_mode)

        functions = [("check_serial", 0x0804841d, 0x08048452)]

        reil_container = ReilContainerBuilder(binary).build(functions)

        # Set up initial state
        initial_state = State(arch_info, mode="initial")

        # Set up stack
        esp = 0xffffceec

        initial_state.write_register("esp", esp)

        # Set up parameters
        user_password_addr = 0xdeadbeef
        user_password_len = 0x6

        initial_state.write_memory(esp + 0x4, 4,
                                   user_password_addr)  # password
        initial_state.write_memory(esp + 0x0, 4,
                                   0x41414141)  # fake return address

        # Each byte of the password should be an ascii char.
        for i in xrange(0, user_password_len):
            value = initial_state.query_memory(user_password_addr + i, 1)

            initial_state.add_constraint(value.uge(0x21))
            initial_state.add_constraint(value.ule(0x7e))

        sym_exec = ReilSymbolicEmulator(arch_info)

        paths = sym_exec.find_address(reil_container,
                                      start=0x0804841d,
                                      end=0x08048452,
                                      find=0x08048451,
                                      avoid=[0x0804843b],
                                      initial_state=initial_state)

        # There's only one way to reach 'find' address.
        self.assertEqual(len(paths), 1)

        final_state = State(arch_info, mode="final")

        user_password_expected = bytearray("AAAAAA")
        user_password = bytearray()

        se_res = SymExecResult(arch_info, initial_state, paths[0], final_state)

        for i in xrange(0, user_password_len):
            value = se_res.query_memory(user_password_addr + i, 1)
            user_password.append(value)

        self.assertEqual(user_password, user_password_expected)
Пример #2
0
    def test_se_6(self):
        binary = BinaryFile(get_full_path("/data/bin/check_serial_6"))

        arch_info = X86ArchitectureInformation(binary.architecture_mode)

        functions = [("expand", 0x0804849b, 0x080484dd)]

        reil_container = ReilContainerBuilder(binary).build(functions)

        # Set up initial state
        initial_state = State(arch_info, mode="initial")

        # Set up stack
        esp = 0xffffceec

        initial_state.write_register("esp", esp)

        # Set up parameters
        out_array_addr = 0xdeadbeef
        in_array_addr = 0xdeadbeef + 0x5

        initial_state.write_memory(esp + 0x04, 4, out_array_addr)  # out
        initial_state.write_memory(esp + 0x08, 4, in_array_addr)  # in
        initial_state.write_memory(esp + 0x0c, 4, 0xAAAAAAAA)
        initial_state.write_memory(esp + 0x10, 4, 0xBBBBBBBB)

        # Set the in array
        for i, b in enumerate(bytearray("\x02\x03\x05\x07")):
            initial_state.write_memory(in_array_addr + i, 1, b)

        #
        # Set up final state
        #
        final_state = State(arch_info, mode="final")

        # Set the B array
        for i, b in enumerate(bytearray("\xFC\xFB\xF5\xF7")):
            final_state.write_memory(out_array_addr + i, 1, b)

        start_addr = 0x0804849b
        end_addr = 0x080484dd

        sym_exec = ReilSymbolicEmulator(arch_info)

        paths = sym_exec.find_state(reil_container,
                                    start=start_addr,
                                    end=end_addr,
                                    initial_state=initial_state,
                                    final_state=final_state)

        # There's only one way to reach 'find' address.
        self.assertEqual(len(paths), 1)

        se_res = SymExecResult(arch_info, initial_state, paths[0], final_state)

        self.assertEqual(se_res.query_memory(esp + 0x4, 4), 0xdeadbeef)
        self.assertEqual(se_res.query_memory(esp + 0x8, 4), 0xdeadbef4)
Пример #3
0
    def test_sample_2(self):
        binary = BinaryFile(get_full_path("/data/bin/x86_sample_2"))
        strategy = RecursiveDescent(self._disassembler, binary.text_section,
                                    self._translator, self._arch_info)
        recoverer = CFGRecoverer(strategy)

        # Recover "main" function.
        bbs, call_targets = recoverer.build(0x0804846d, 0x080484a3)

        self.assertEqual(len(bbs), 4)

        cfg = ControlFlowGraph(bbs, name="main")

        self.assertEqual(cfg.start_address, 0x0804846d)
        self.assertEqual(cfg.end_address, 0x080484a3)
        self.assertEqual(len(cfg.basic_blocks), 4)

        bb_entry = cfg.find_basic_block(0x0804846d)
        self.assertEqual(len(bb_entry.branches), 2)
        self.assertEqual(bb_entry.taken_branch, 0x08048491)
        self.assertEqual(bb_entry.not_taken_branch, 0x0804848a)

        bb_taken = cfg.find_basic_block(0x08048491)
        self.assertEqual(len(bb_taken.branches), 1)
        self.assertEqual(bb_taken.taken_branch, None)
        self.assertEqual(bb_taken.not_taken_branch, None)
        self.assertEqual(bb_taken.direct_branch, 0x08048496)

        bb_not_taken = cfg.find_basic_block(0x0804848a)
        self.assertEqual(len(bb_not_taken.branches), 1)
        self.assertEqual(bb_not_taken.taken_branch, None)
        self.assertEqual(bb_not_taken.not_taken_branch, None)
        self.assertEqual(bb_not_taken.direct_branch, 0x08048496)

        # Recover "func_1" function.
        bbs, call_targets = recoverer.build(0x0804843b, 0x8048453)

        self.assertEqual(len(bbs), 1)

        cfg = ControlFlowGraph(bbs, name="main")

        self.assertEqual(cfg.start_address, 0x0804843b)
        self.assertEqual(cfg.end_address, 0x8048453)
        self.assertEqual(len(cfg.basic_blocks), 1)

        # Recover "func_2" function.
        bbs, call_targets = recoverer.build(0x08048454, 0x0804846c)

        self.assertEqual(len(bbs), 1)

        cfg = ControlFlowGraph(bbs, name="main")

        self.assertEqual(cfg.start_address, 0x08048454)
        self.assertEqual(cfg.end_address, 0x0804846c)
        self.assertEqual(len(cfg.basic_blocks), 1)
Пример #4
0
    def test_emulate_arm(self):
        binary = BinaryFile(get_full_path("./samples/bin/loop-simple.arm"))
        arch_mode = ARCH_ARM_MODE_ARM
        arch_info = ArmArchitectureInformation(arch_mode)
        ir_emulator = ReilEmulator(arch_info)
        disassembler = ArmDisassembler(architecture_mode=ARCH_ARM_MODE_ARM)
        ir_translator = ArmTranslator(architecture_mode=ARCH_ARM_MODE_ARM)

        emu = Emulator(arch_info, ir_emulator, ir_translator, disassembler)

        emu.load_binary(binary)

        emu.emulate(0x10400, 0x10460, {}, None, True)
Пример #5
0
    def test_emulate_x86_64(self):
        binary = BinaryFile(get_full_path("./samples/bin/loop-simple.x86_64"))
        arch_mode = ARCH_X86_MODE_64
        arch_info = X86ArchitectureInformation(arch_mode)
        ir_emulator = ReilEmulator(arch_info)
        disassembler = X86Disassembler(ARCH_X86_MODE_64)
        ir_translator = X86Translator(ARCH_X86_MODE_64)

        emu = Emulator(arch_info, ir_emulator, ir_translator, disassembler)

        emu.load_binary(binary)

        emu.emulate(0x4004d6, 0x400507, {}, None, False)
Пример #6
0
    def test_sample_1(self):
        binary = BinaryFile(get_full_path("/data/bin/x86_sample_1"))
        strategy = RecursiveDescent(self._disassembler, binary.text_section,
                                    self._translator, self._arch_info)
        recoverer = CFGRecoverer(strategy)

        bbs, call_targets = recoverer.build(0x0804840b, 0x08048438)

        self.assertEqual(len(bbs), 1)

        cfg = ControlFlowGraph(bbs, name="main")

        self.assertEqual(cfg.start_address, 0x0804840b)
        self.assertEqual(cfg.end_address, 0x08048438)
        self.assertEqual(len(cfg.basic_blocks), 1)
Пример #7
0
def main():
    # Process program arguments.
    parser = init_parser()
    args = parser.parse_args()

    # Open binary.
    binary = BinaryFile(args.binary)

    # Check binary arch and mode.
    if binary.architecture != ARCH_X86 or \
            binary.architecture_mode not in [ARCH_X86_MODE_32, ARCH_X86_MODE_64]:
        print("[!] Architecture not supported.")
        sys.exit(1)

    # Load architecture information for the binary.
    arch_info = X86ArchitectureInformation(binary.architecture_mode)

    # Extract entrypoint (in case a starting address was not provided.)
    start_address = int(args.start_address,
                        16) if args.start_address else binary.entry_point

    # Prepare options.
    options = DotDict({})
    options.abort = args.abort
    options.color = args.color
    options.verbose = args.verbose

    print("[+] Loading trace...")
    asm_trace = parse_trace(args.trace,
                            X86Parser(arch_info.architecture_mode),
                            start_address=start_address)

    print("[+] Replaying trace...")
    analyzer = AsmReplayAnalyzer(arch_info, asm_trace, start_address, options)

    analyzer.run()
Пример #8
0
def solve():
    #
    # Load binary
    #
    binary = BinaryFile("bin/very_success")

    arch_info = X86ArchitectureInformation(binary.architecture_mode)

    # Create a REIL container for the function of interest
    functions = [("sub_401084", 0x00401084, 0x004010de)]

    reil_container = ReilContainerBuilder(binary).build(functions)

    #
    # Set up initial state
    #
    initial_state = State(arch_info, mode="initial")

    # Set up stack
    esp = 0xffffceec

    initial_state.write_register("esp", esp)

    # Set up parameters
    user_password_addr = 0x00402159
    user_password_len = 0x25
    ref_key_addr = 0x004010e4

    initial_state.write_memory(esp + 0xc, 4, user_password_len)
    initial_state.write_memory(esp + 0x8, 4, user_password_addr)
    initial_state.write_memory(esp + 0x4, 4, ref_key_addr)
    initial_state.write_memory(esp + 0x0, 4, 0x41414141)  # return address

    # Set memory
    for i in xrange(user_password_len):
        initial_state.write_memory(ref_key_addr + i, 1,
                                   ord(binary.text_section[ref_key_addr + i]))

    #
    # Run concolic execution
    #
    sym_exec = ReilSymbolicEmulator(arch_info)

    paths = sym_exec.find_address(reil_container,
                                  start=0x00401084,
                                  end=0x004010de,
                                  find=0x004010d5,
                                  avoid=[0x004010d7],
                                  initial_state=initial_state)

    # There's only one way to reach 'find' address.
    assert len(paths) == 1

    #
    # Query input buffer and print content
    #
    final_state = State(arch_info, mode="final")

    se_res = SymExecResult(arch_info, initial_state, paths[0], final_state)

    user_password = bytearray()

    for i in xrange(user_password_len):
        user_password.append(se_res.query_memory(user_password_addr + i, 1))

    print("User password: {}".format(user_password))

    assert user_password == bytearray("*****@*****.**")
Пример #9
0
def solve():
    #
    # Load Binary
    #
    binary = BinaryFile("bin/toyproject.exe")

    arch_info = X86ArchitectureInformation(binary.architecture_mode)

    # Identify functions of interest
    functions = [("sub_4010ec", 0x004010ec, 0x004010ec + 0x3a)]

    # Create a REIL container
    reil_container_builder = ReilContainerBuilder(binary)

    reil_container = reil_container_builder.build(functions)

    #
    # Set up initial state
    #
    initial_state = State(arch_info, mode="initial")

    # Set up stack
    esp = 0x00001500

    initial_state.write_register("esp", esp)

    # Set up parameters
    out_array_addr = esp - 0x25
    in_array_addr = 0x4093a8

    initial_state.write_memory(esp + 0x0, 4, 0x41414141)  # fake return address

    # TODO: Find a way to mark 'x' and 'y' as symbolic variables.
    # initial_state.write_memory(esp + 0x4, 4, x) # Mark as Symbolic
    # initial_state.write_memory(esp + 0x8, 4, y) # Mark as Symbolic

    # Set the A array
    in_array_expected = bytearray(__get_in_array())

    for i in range(len(in_array_expected)):
        initial_state.write_memory(in_array_addr + i, 1, in_array_expected[i])

    #
    # Set up final state
    #
    final_state = State(arch_info, mode="final")

    # Set the B array
    out_array_expected = bytearray(__get_out_array(), encoding='ascii')

    for i in range(32):
        # Avoid trivial solution
        initial_state.write_memory(out_array_addr + i, 1, 0)

        # Assert final (desired) state
        final_state.write_memory(out_array_addr + i, 1, out_array_expected[i])

    #
    # Run concolic execution
    #
    sym_exec = ReilSymbolicEmulator(arch_info)

    paths = sym_exec.find_state(reil_container,
                                start=0x004010ec,
                                end=0x0040111d,
                                initial_state=initial_state,
                                final_state=final_state)

    # There's only one way to reach the final state.
    # assert len(paths) == 1

    print("[+] Number of paths: {}".format(len(paths)))

    # for index, path in enumerate(paths):
    #     __save_path(path, index)

    #
    # Query input buffer and print content
    #
    print("A (in)  : {:s}".format(" ".join(
        ["{:02x}".format(b) for b in in_array_expected])))
    print("B (out) : {:s}".format(" ".join(
        ["{:02x}".format(b) for b in out_array_expected])))

    if len(paths) > 0:
        se_res = SymExecResult(arch_info, initial_state, paths[0], final_state)

        print("x: {0:#010x} ({0:d})".format(se_res.query_memory(esp + 0x4, 4)))
        print("y: {0:#010x} ({0:d})".format(se_res.query_memory(esp + 0x8, 4)))
    else:
        print("[-] State Not Found!")