Skip to content

Commit

Permalink
Improve GEF running under winedbg
Browse files Browse the repository at this point in the history
  • Loading branch information
clubby789 committed May 8, 2024
1 parent 18c1f7c commit b15d41b
Showing 1 changed file with 73 additions and 1 deletion.
74 changes: 73 additions & 1 deletion gef.py
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,14 @@ def is_alive() -> bool:
return False


def is_wine() -> bool:
"""Check we're running under winedbg."""
try:
return "hwnd" in gdb.execute("monitor wnd", to_string=True)
except Exception:
return False


def calling_function() -> Optional[str]:
"""Return the name of the calling function"""
try:
Expand Down Expand Up @@ -646,6 +654,15 @@ def from_monitor_info_mem(cls, perm_str: str) -> "Permission":
if perm_str[2] == "w": perm |= Permission.WRITE
return perm

@classmethod
def from_monitor_mem(cls, perm_str: str) -> "Permission":
perm = cls(0)
perm_str = perm_str.ljust(3)
if perm_str[0] == "R": perm |= Permission.READ
if perm_str[1] == "W": perm |= Permission.WRITE
if perm_str[2] == "X": perm |= Permission.EXECUTE
return perm

@classmethod
def from_info_mem(cls, perm_str: str) -> "Permission":
perm = cls(0)
Expand Down Expand Up @@ -2833,7 +2850,7 @@ def is_branch_taken(self, insn: Instruction) -> Tuple[bool, str]:


class X86(Architecture):
aliases: Tuple[Union[str, Elf.Abi], ...] = ("X86", Elf.Abi.X86_32)
aliases: Tuple[Union[str, Elf.Abi], ...] = ("X86", "i386", Elf.Abi.X86_32)
arch = "X86"
mode = "32"

Expand Down Expand Up @@ -3771,6 +3788,8 @@ def reset_architecture(arch: Optional[str] = None) -> None:
# check for bin running
if is_alive():
gdb_arch = gdb.selected_frame().architecture().name()
if gdb_arch in arches:
gef.arch = arches[gdb_arch]()
preciser_arch = next((a for a in arches.values() if a.supports_gdb_arch(gdb_arch)), None)
if preciser_arch:
gef.arch = preciser_arch()
Expand Down Expand Up @@ -7512,6 +7531,9 @@ def do_invoke(self, argv: List[str]) -> None:
if not self["enable"] or gef.ui.context_hidden:
return

if type(gef.arch) == GenericArchitecture:
return

if not all(_ in self.layout_mapping for _ in argv):
self.usage()
return
Expand Down Expand Up @@ -10632,6 +10654,11 @@ def __parse_maps(self) -> Optional[List[Section]]:
except:
pass

try:
return list(self.parse_monitor_mem())
except:
pass

raise RuntimeError("Failed to get memory layout")

@classmethod
Expand Down Expand Up @@ -10747,6 +10774,37 @@ def parse_monitor_info_mem(cls) -> Generator[Section, None, None]:
offset=off,
permission=perm)

@classmethod
def parse_monitor_mem(cls) -> Generator[Section, None, None]:
"""If we're running under winedbg, we can use `monitor mem` to get memory mappings
This can raise an exception, which the memory manager takes to mean
that this method does not work to get a map.
"""

# Expected output format:
# Address Size State Type RWX
# 00000000 00110000 free
# 00110000 00003000 commit mapped R X
# ...

stream = StringIO(gdb.execute("monitor mem", to_string=True))
for line in stream:
if line.startswith("Address"):
continue
try:
start, size, _, _, perms = line.split(maxsplit=5)
start = int(start, 16)
size = int(size, 16)
perms = perms.ljust(3)
end = start + size
except ValueError:
continue

perm = Permission.from_monitor_mem(perms)
yield Section(page_start=start,
page_end=end,
permission=perm)

@staticmethod
def parse_info_mem():
"""Get the memory mapping from GDB's command `info mem`. This can be
Expand Down Expand Up @@ -11104,6 +11162,8 @@ def auxiliary_vector(self) -> Optional[Dict[str, int]]:
return None
if is_qemu_system():
return None
if is_wine():
return None
if not self._auxiliary_vector:
auxiliary_vector = {}
auxv_info = gdb.execute("info auxv", to_string=True) or ""
Expand Down Expand Up @@ -11221,6 +11281,7 @@ class RemoteMode(enum.IntEnum):
GDBSERVER = 0
QEMU = 1
RR = 2
WINEDBG = 3

def __str__(self):
return self.name
Expand All @@ -11235,6 +11296,8 @@ def prompt_string(self) -> str:
return Color.boldify("(rr) ")
if self == GefRemoteSessionManager.RemoteMode.GDBSERVER:
return Color.boldify("(remote) ")
if self == GefRemoteSessionManager.RemoteMode.WINEDBG:
return Color.boldify("(winedbg) ")
raise AttributeError("Unknown value")

def __init__(self, host: str, port: int, pid: int =-1, qemu: Optional[pathlib.Path] = None) -> None:
Expand All @@ -11249,6 +11312,8 @@ def __init__(self, host: str, port: int, pid: int =-1, qemu: Optional[pathlib.Pa
self._mode = GefRemoteSessionManager.RemoteMode.QEMU
elif os.environ.get("GDB_UNDER_RR", None) == "1":
self._mode = GefRemoteSessionManager.RemoteMode.RR
elif is_wine():
self._mode = GefRemoteSessionManager.RemoteMode.WINEDBG
else:
self._mode = GefRemoteSessionManager.RemoteMode.GDBSERVER

Expand Down Expand Up @@ -11354,6 +11419,9 @@ def setup(self) -> bool:
elif self.mode == GefRemoteSessionManager.RemoteMode.RR:
dbg(f"Setting up as rr session")
self.__setup_rr()
elif self.mode == GefRemoteSessionManager.RemoteMode.WINEDBG:
dbg(f"Setting up as winedbg session")
self.__setup_winedbg()
elif self.mode == GefRemoteSessionManager.RemoteMode.GDBSERVER:
dbg(f"Setting up as remote session")
self.__setup_remote()
Expand Down Expand Up @@ -11415,6 +11483,10 @@ def __setup_remote(self) -> bool:

return True

def __setup_winedbg(self) -> bool:
reset_architecture()
return True

def __setup_rr(self) -> bool:
#
# Simply override the local root path, the binary must exist
Expand Down

0 comments on commit b15d41b

Please sign in to comment.