From 44471dfd911f969f9b311fb7dcf9f0a0770ff12f Mon Sep 17 00:00:00 2001 From: veritas501 Date: Tue, 27 Apr 2021 12:57:34 +0800 Subject: [PATCH] fix(emulate): refix emulate, let it works correct on unicorn-1.0.2rc1 ~ unicorn-1.0.2 --- pwndbg/disasm/__init__.py | 13 +++---------- pwndbg/emu/emulator.py | 10 ++++++++-- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/pwndbg/disasm/__init__.py b/pwndbg/disasm/__init__.py index 744e0c085..59386d93f 100644 --- a/pwndbg/disasm/__init__.py +++ b/pwndbg/disasm/__init__.py @@ -218,6 +218,8 @@ def near(address, instructions=1, emulate=False, show_prev_insns=True): # If we hit the current instruction, we can do emulation going forward from there. if address == pc and emulate: emu = pwndbg.emu.emulator.Emulator() + # skip current line + emu.single_step() # Now find all of the instructions moving forward. # @@ -225,8 +227,6 @@ def near(address, instructions=1, emulate=False, show_prev_insns=True): # and the instruction at 'address'. insn = current total_instructions = 1 + (2*instructions) - last_emu_target = None - target_candidate = address while insn and len(insns) < total_instructions: target = insn.target @@ -239,14 +239,7 @@ def near(address, instructions=1, emulate=False, show_prev_insns=True): # If we initialized the emulator and emulation is still enabled, we can use it # to figure out the next instruction. if emu: - # For whatever reason, the first instruction is emulated twice on - # unicorn-1.0.2rc1~unicorn-1.0.2rc3, but not on >= unicorn-1.0.2rc4. - # If the address is equal with the last one, skip it - last_emu_target = target_candidate - while last_emu_target == target_candidate: - target_candidate, size_candidate = emu.single_step() - if not target_candidate: - break + target_candidate, size_candidate = emu.single_step() if None not in (target_candidate, size_candidate): target = target_candidate diff --git a/pwndbg/emu/emulator.py b/pwndbg/emu/emulator.py index 53b769543..1511849d4 100644 --- a/pwndbg/emu/emulator.py +++ b/pwndbg/emu/emulator.py @@ -432,6 +432,7 @@ class Emulator: debug("# Single-stepping at %#x: %s %s" % (pc, insn.mnemonic, insn.op_str)) try: + self.single_step_hook_hit_count = 0 self.emulate_with_hook(self.single_step_hook_code, count=1) except U.unicorn.UcError as e: self._single_step = (None, None) @@ -446,8 +447,13 @@ class Emulator: a = self.single_step(pc) def single_step_hook_code(self, _uc, address, instruction_size, _user_data): - debug("# single_step: %#-8x" % address) - self._single_step = (address, instruction_size) + # For whatever reason, the hook will hit twice on + # unicorn >= 1.0.2rc4, but not on unicorn-1.0.2rc1~unicorn-1.0.2rc3, + # So we use a counter to ensure the code run only once + if self.single_step_hook_hit_count == 0: + debug("# single_step: %#-8x" % address) + self._single_step = (address, instruction_size) + self.single_step_hook_hit_count += 1 def dumpregs(self): for reg in list(self.regs.retaddr) + list(self.regs.misc) + list(self.regs.common) + list(self.regs.flags):