Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement exception hooks #65

Merged
merged 3 commits into from
Mar 16, 2023
Merged

Implement exception hooks #65

merged 3 commits into from
Mar 16, 2023

Conversation

mrexodia
Copy link
Owner

@mrexodia mrexodia commented Mar 16, 2023

Closes #41 thanks to @oopsmishap for the initial POC!

Here is how you could add your own breakpoint support:

@dataclass
class BreakpointInfo:
    address: int
    original: bytes
    callback: Callable[[], None]

class MyDumpulator(Dumpulator):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self._breakpoints: Dict[int, BreakpointInfo] = {}
        self._breakpoint_step: Optional[BreakpointInfo] = None
        self.set_exception_hook(self.exception_hook)

    def set_breakpoint(self, address: Union[int, str], callback: Callable[[], None]):
        if isinstance(address, str):
            module_name, export_name = address.split(":")
            module = self.modules.find(module_name)
            if module is None:
                raise KeyError(f"Module '{module_name}' not found")
            export = module.find_export(export_name)
            if export is None:
                raise KeyError(f"Export '{export_name}' not found in module '{module_name}'")
            assert export.forward is None
            address: int = export.address
        assert address not in self._breakpoints
        self._breakpoints[address] = BreakpointInfo(address, self.read(address, 1), callback)
        self.write(address, b"\xCC")

    def remove_breakpoint(self, address: int):
        assert address in self._breakpoints
        bp = self._breakpoints[address]
        self.write(bp.address, bp.original)
        del self._breakpoints[address]

    def exception_hook(self, exception: ExceptionInfo) -> Optional[int]:
        if exception.type == ExceptionType.Interrupt:
            if exception.interrupt_number == 3:  # int3
                # Find the breakpoint
                bp = self._breakpoints.get(self.regs.cip - 1)
                if bp is None:
                    print(f"Unexpected int3 at {hex(self.regs.cip)}, ignoring")
                    return None
                print(f"Reached breakpoint at {hex(bp.address)}")

                # Execute the breakpoint callback
                self.regs.cip -= 1
                bp.callback()

                # Restore the breakpoint if it wasn't removed
                if bp.address in self._breakpoints:
                    self.write(bp.address, bp.original)
                    self.regs.eflags |= 0x100  # trap flag
                    self._breakpoint_step = bp

                # Resume execution at the CIP (the callback might change it)
                return self.regs.cip
            elif exception.interrupt_number == 1:  # single step
                if self._breakpoint_step is None:
                    print(f"Unexpected single step at {hex(self.regs.cip)}")
                    return None

                print("Single stepping after breakpoint")
                self.regs.eflags &= ~0x100  # remove trap flag
                self.write(self._breakpoint_step.address, b"\xCC")
                self._breakpoint_step = None
                return self.regs.cip

        # Let the original exception handler do this
        return None

@mrexodia mrexodia force-pushed the exception-hooks branch 2 times, most recently from fd922bf to e6cc310 Compare March 16, 2023 18:46
@mrexodia mrexodia merged commit b22e8e3 into main Mar 16, 2023
@mrexodia mrexodia deleted the exception-hooks branch March 16, 2023 18:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add support for exception hooks
1 participant