Skip to content

Commit

Permalink
Determine the actual canary location when possible
Browse files Browse the repository at this point in the history
  • Loading branch information
clubby789 committed Nov 11, 2022
1 parent 1bf74a8 commit c3c4f0a
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 11 deletions.
35 changes: 25 additions & 10 deletions gef.py
Original file line number Diff line number Diff line change
Expand Up @@ -2260,6 +2260,9 @@ def is_branch_taken(self, insn: Instruction) -> Tuple[bool, str]:
def get_ra(self, insn: Instruction, frame: "gdb.Frame") -> Optional[int]:
raise NotImplementedError

def canary_address(self) -> int:
raise NotImplementedError

@classmethod
def mprotect_asm(cls, addr: int, size: int, perm: Permission) -> str:
raise NotImplementedError
Expand Down Expand Up @@ -2920,6 +2923,8 @@ def mprotect_asm(cls, addr: int, size: int, perm: Permission) -> str:
]
return "; ".join(insns)

def canary_address(self) -> int:
return self.register("fs_base") + 0x28

class PowerPC(Architecture):
aliases = ("PowerPC", Elf.Abi.POWERPC, "PPC")
Expand Down Expand Up @@ -10439,7 +10444,6 @@ def reset_caches(self) -> None:
self._os = None
self._pid = None
self._file = None
self._canary = None
self._maps: Optional[pathlib.Path] = None
self._root: Optional[pathlib.Path] = None
return
Expand Down Expand Up @@ -10513,15 +10517,26 @@ def pagesize(self) -> int:

@property
def canary(self) -> Optional[Tuple[int, int]]:
"""Returns a tuple of the canary address and value, read from the auxiliary vector."""
auxval = self.auxiliary_vector
if not auxval:
return None
canary_location = auxval["AT_RANDOM"]
canary = gef.memory.read_integer(canary_location)
canary &= ~0xFF
self._canary = (canary, canary_location)
return self._canary
"""Return a tuple of the canary address and value, read from the canonical
location if supported by the architecture. Otherwise, read from the auxiliary
vector."""
try:
canary_location = gef.arch.canary_address()
canary = gef.memory.read_integer(canary_location)
except NotImplementedError:
# Fall back to `AT_RANDOM`, which is the original source
# of the canary value but not the canonical location
auxval = self.auxiliary_vector
if not auxval:
return None
canary_location = auxval["AT_RANDOM"]
canary = gef.memory.read_integer(canary_location)
warn("Canary was read from auxiliary vector")
# The canary is created by reading a word from `AT_RANDOM`
# and zeroing the lowest byte
canary &= ~0xFF

return canary, canary_location

@property
def maps(self) -> Optional[pathlib.Path]:
Expand Down
10 changes: 9 additions & 1 deletion tests/commands/canary.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from tests.utils import gdb_start_silent_cmd, gdb_run_cmd, _target
from tests.utils import GefUnitTestGeneric

import platform

class CanaryCommand(GefUnitTestGeneric):
"""`canary` command test module"""
Expand All @@ -16,3 +16,11 @@ def test_cmd_canary(self):
res = gdb_start_silent_cmd("canary", target=_target("canary"))
self.assertNoException(res)
self.assertIn("The canary of process", res)
# On other platforms, we read the canary from the auxiliary vector -
# overwriting this value does not overwrite the in-use canary so it
# is not tested
if platform.machine() == "x86_64":
patch = r"pi gef.memory.write(gef.arch.canary_address(), b'\xef\xbe\xad\xde')"
res = gdb_start_silent_cmd(patch, target=_target("canary"), after=["canary"])
self.assertNoException(res)
self.assertIn("0xdeadbeef", res)

0 comments on commit c3c4f0a

Please sign in to comment.