mirror of https://github.com/pwndbg/pwndbg
add patch command (#1150)
* add patch command This commit adds the `patch`, `patch_list` and `patch_revert` commands and adds the `pwntools==4.8.0` as Pwndbg dependency. The current implementation could be further improved by: - adding tests :) - maybe moving `patch_list` and `patch_revert` to `patch --list` and `patch --revert` flags? - better handling of incorrect args/pwnlib exceptions * lint
This commit is contained in:
parent
cc3f86d5bc
commit
446f5d5ae2
|
@ -70,4 +70,6 @@ if encoding != "UTF-8":
|
|||
print("Make sure that en_US.UTF-8 is activated in /etc/locale.gen and you called locale-gen")
|
||||
print("******")
|
||||
|
||||
environ["PWNLIB_NOTERM"] = "1"
|
||||
|
||||
import pwndbg # noqa: F401
|
||||
|
|
|
@ -31,6 +31,7 @@ import pwndbg.commands.misc
|
|||
import pwndbg.commands.mprotect
|
||||
import pwndbg.commands.next
|
||||
import pwndbg.commands.p2p
|
||||
import pwndbg.commands.patch
|
||||
import pwndbg.commands.peda
|
||||
import pwndbg.commands.pie
|
||||
import pwndbg.commands.probeleak
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
import argparse
|
||||
|
||||
from pwnlib.asm import asm
|
||||
from pwnlib.asm import disasm
|
||||
|
||||
import pwndbg.color.message as message
|
||||
import pwndbg.commands
|
||||
import pwndbg.gdblib.memory
|
||||
import pwndbg.lib.memoize
|
||||
|
||||
# Keep old patches made so we can revert them
|
||||
patches = {}
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(description="Patches given instruction with given code or bytes")
|
||||
parser.add_argument("address", type=int, help="The address to patch")
|
||||
parser.add_argument("ins", type=str, help="instruction[s]")
|
||||
|
||||
|
||||
@pwndbg.commands.ArgparsedCommand(parser)
|
||||
@pwndbg.commands.OnlyWhenRunning
|
||||
def patch(address, ins):
|
||||
new_mem = asm(ins, arch=pwndbg.gdblib.arch.current)
|
||||
|
||||
old_mem = pwndbg.gdblib.memory.read(address, len(new_mem))
|
||||
|
||||
patches[address] = (old_mem, new_mem)
|
||||
|
||||
pwndbg.gdblib.memory.write(address, new_mem)
|
||||
|
||||
pwndbg.lib.memoize.reset()
|
||||
|
||||
|
||||
parser2 = argparse.ArgumentParser(description="Revert patch at given address")
|
||||
parser2.add_argument("address", type=int, help="Address to revert patch on")
|
||||
|
||||
|
||||
@pwndbg.commands.ArgparsedCommand(parser2)
|
||||
@pwndbg.commands.OnlyWhenRunning
|
||||
def patch_revert(address):
|
||||
if not patches:
|
||||
print(message.notice("No patches to revert"))
|
||||
return
|
||||
|
||||
if address == -1:
|
||||
for addr, (old, _new) in patches.items():
|
||||
pwndbg.gdblib.memory.write(addr, old)
|
||||
print(message.notice("Reverted patch at %#x" % addr))
|
||||
patches.clear()
|
||||
else:
|
||||
old, _new = patches[address]
|
||||
pwndbg.gdblib.memory.write(address, old)
|
||||
|
||||
pwndbg.lib.memoize.reset()
|
||||
|
||||
|
||||
parser3 = argparse.ArgumentParser(description="List all patches")
|
||||
|
||||
|
||||
@pwndbg.commands.ArgparsedCommand(parser3)
|
||||
@pwndbg.commands.OnlyWhenRunning
|
||||
def patch_list():
|
||||
if not patches:
|
||||
print(message.hint("No patches to list"))
|
||||
return
|
||||
|
||||
print(message.hint("Patches:"))
|
||||
for addr, (old, new) in patches.items():
|
||||
old_insns = disasm(old, arch=pwndbg.gdblib.arch.current)
|
||||
new_insns = disasm(new, arch=pwndbg.gdblib.arch.current)
|
||||
|
||||
print(
|
||||
message.hint("Patch at"),
|
||||
message.warning("%#x:" % addr),
|
||||
message.hint("from"),
|
||||
message.warning(old_insns.replace("\n", "; ")),
|
||||
message.hint("to"),
|
||||
message.warning(new_insns.replace("\n", "; ")),
|
||||
)
|
|
@ -21,3 +21,4 @@ tomli==2.0.1; python_version >= '3.7'
|
|||
tomli==1.2.3; python_version < '3.7'
|
||||
unicorn==2.0.0; python_version >= '3.7'
|
||||
unicorn==2.0.0rc7; python_version < '3.7'
|
||||
pwntools==4.8.0
|
||||
|
|
Loading…
Reference in New Issue