Skip to content

Commit

Permalink
Fix early arch detection & the 'Cannot find ELF base!' warning
Browse files Browse the repository at this point in the history
Before this commit, when we did `gdb /bin/ls` and then `entry`, we could see a "Cannot find ELF base!" warning. This occured, because the `pwndbg.arch.ptrmask` was incorrectly set and then the `find_elf_magic` was using the `pwndbg.arch.ptrmask` which was 0xffFFffFF and made an early return. As a result of this early return, the "Cannot find ELF base!" warning was emitted.

The reason for incorrect early arch detection is that we used the `gdb.newest_frame().architecture().name()` API while the binary was not using in here:
```python
 @pwndbg.events.start
 @pwndbg.events.stop
 @pwndbg.events.new_objfile
 def update():
     m = sys.modules[__name__]

     try:
         m.current = fix_arch(gdb.newest_frame().architecture().name())
     except Exception:
         return

     m.ptrsize = pwndbg.typeinfo.ptrsize
     m.ptrmask = (1 << 8*pwndbg.typeinfo.ptrsize)-1
```

And if the binary was not running, we just returned early and did not set `pwndbg.arch.ptrsize` and `pwndbg.arch.ptrmask` at all, leaving them at their default values.

Now, those values were often eventually fixed, but this occured by chance as the `new_objfile` was executed!

Anyway, starting from this commit, we will detect the arch from `gdb.newest_frame().architecture().name()` only if the process is running and if it is not, we will fallback to the `show architecture` GDB command and parse it, hoping we detect the arch properly. In case we don't, or, we don't support the given arch, we raise a `RuntimeError` currently.

Also, as a side note: the `find_elf_magic` from `elf.py` can be optimized to instead of doing 4kB steps over pages, to just look at the begining of a page. Otherwise, if this doesn't work, we are most likely on a target that may not have an ELF magic/header at all, so we shouldn't bother about it. This fix is done in the next commit.
  • Loading branch information
disconnect3d committed Aug 21, 2021
1 parent 8faa634 commit 66d5d6c
Showing 1 changed file with 17 additions and 12 deletions.
29 changes: 17 additions & 12 deletions pwndbg/arch.py
Expand Up @@ -20,33 +20,38 @@
native_endian = str(sys.byteorder)


def fix_arch(arch):
for match in ['x86-64', 'i386', 'mips', 'powerpc', 'sparc', 'aarch64']:
def _get_arch():
not_exactly_arch = False

if pwndbg.proc.alive:
arch = gdb.newest_frame().architecture().name()
else:
arch = gdb.execute("show architecture", to_string=True).strip()
not_exactly_arch = True

# Below, we fix the fetched architecture
for match in ('x86-64', 'i386', 'aarch64', 'mips', 'powerpc', 'sparc'):
if match in arch:
return match

# Distinguish between Cortex-M and other ARM
if 'arm' in arch:
return 'armcm' if '-m' in arch else 'arm'

if not_exactly_arch:
raise RuntimeError("Could not deduce architecture from: %s" % arch)

return arch



@pwndbg.events.start
@pwndbg.events.stop
@pwndbg.events.new_objfile
def update():
m = sys.modules[__name__]

# GDB 7.7 (Ubuntu Trusty) does not like selected_frame() when EBP/RBP
# is not mapped / pounts to an invalid address.
#
# As a work-around for Trusty users, handle the exception and bail.
# This may lead to inaccurate results, but there's not much to be done.
try:
m.current = fix_arch(gdb.newest_frame().architecture().name())
except Exception:
return

m.current = _get_arch()
m.ptrsize = pwndbg.typeinfo.ptrsize
m.ptrmask = (1 << 8*pwndbg.typeinfo.ptrsize)-1

Expand Down

0 comments on commit 66d5d6c

Please sign in to comment.