|
12 | 12 | if str(ROOT) not in sys.path: |
13 | 13 | sys.path.insert(0, str(ROOT)) |
14 | 14 |
|
15 | | -from capstone import CS_GRP_CALL, CS_GRP_JUMP, CS_OP_IMM, CS_OP_MEM, CsInsn |
| 15 | +from capstone import CS_GRP_JUMP, CS_OP_IMM, CS_OP_MEM |
16 | 16 | from capstone.x86_const import X86_REG_RIP |
17 | 17 | from llvm import IntPredicate, Opcode, Value, create_context |
18 | 18 |
|
@@ -707,26 +707,40 @@ def run(self) -> ConcolicResult: |
707 | 707 | for step in range(self.cfg.max_steps): |
708 | 708 | state.steps = step + 1 |
709 | 709 | code = self.container.get_data(rip, 15) |
710 | | - insn = sem.cs_disasm(rip, code) |
711 | | - instruction = f"{insn.mnemonic} {insn.op_str}".strip() |
712 | | - self._record_seed_candidates(insn, state) |
| 710 | + try: |
| 711 | + insn = sem.cs_disasm(rip, code) |
| 712 | + except ValueError: |
| 713 | + insn = None |
| 714 | + instruction = f"invalid {code[0]:#04x}" |
| 715 | + else: |
| 716 | + instruction = f"{insn.mnemonic} {insn.op_str}".strip() |
| 717 | + self._record_seed_candidates(insn, state) |
713 | 718 | if len(self.trace) < self.cfg.trace_limit: |
714 | 719 | self.trace.append(f"{rip:#x}: {instruction}") |
715 | 720 |
|
716 | | - if insn.group(CS_GRP_CALL) and rip in self.cfg.follow_calls: |
717 | | - self._lift_followed_call(sem, insn) |
718 | | - else: |
719 | | - block = sem.get_or_create_block(rip) |
720 | | - if ( |
721 | | - block.first_instruction is not None |
722 | | - and block.first_instruction.opcode == Opcode.Ret |
723 | | - ): |
| 721 | + block = sem.get_or_create_block(rip) |
| 722 | + if ( |
| 723 | + block.first_instruction is not None |
| 724 | + and block.first_instruction.opcode == Opcode.Ret |
| 725 | + ): |
| 726 | + if insn is None: |
| 727 | + sem.lift_invalid(rip) |
| 728 | + else: |
724 | 729 | sem.lift_instruction(insn) |
725 | 730 |
|
726 | 731 | block = sem.insn_blocks[rip] |
727 | 732 | block_result = interp.execute_block(block) |
728 | 733 | if isinstance(block_result, BoundaryResult): |
729 | 734 | boundary = cast("BoundaryResult[SymVal]", block_result) |
| 735 | + if boundary.name == "__striga_call" and rip in self.cfg.follow_calls: |
| 736 | + target = boundary.target.concrete |
| 737 | + if target is not None: |
| 738 | + if len(self.trace) < self.cfg.trace_limit: |
| 739 | + self.trace.append( |
| 740 | + f"{rip:#x}: follow __striga_call -> {target:#x}" |
| 741 | + ) |
| 742 | + rip = target |
| 743 | + continue |
730 | 744 | state.boundary_call = boundary.name |
731 | 745 | state.boundary_value = boundary.target |
732 | 746 | stop = rip |
@@ -820,24 +834,6 @@ def _record_seed_candidates(self, insn, state: ExecutionState) -> None: |
820 | 834 | Seed("lea_addr", insn.address, addr, f"lea {insn.op_str}"), |
821 | 835 | ) |
822 | 836 |
|
823 | | - def _lift_followed_call(self, sem: Semantics, insn: CsInsn) -> None: |
824 | | - block = sem.get_or_create_block(insn.address) |
825 | | - if ( |
826 | | - block.first_instruction is not None |
827 | | - and block.first_instruction.opcode == Opcode.Ret |
828 | | - ): |
829 | | - block.first_instruction.erase_from_parent() |
830 | | - else: |
831 | | - return |
832 | | - target = insn.operands[0].imm |
833 | | - fallthrough = insn.address + insn.size |
834 | | - with block.create_builder() as ir: |
835 | | - sem.ir = ir |
836 | | - sem.insn = insn |
837 | | - sem.push(sem.const64(fallthrough)) |
838 | | - ir.br(sem.get_or_create_block(target)) |
839 | | - sem.module.verify_or_raise() |
840 | | - |
841 | 837 | def _write_outputs(self, result: ConcolicResult) -> None: |
842 | 838 | self.cfg.out_dir.mkdir(parents=True, exist_ok=True) |
843 | 839 | (self.cfg.out_dir / "trace.txt").write_text( |
|
0 commit comments