Skip to content

Commit 60df810

Browse files
authored
corefile: Update NT_XXX type names for pyelftools==0.25 (#1198)
* corefile: Update NT_XXX type names for pyelftools==0.25 * travis: Do not use Sphinx version 1.8.0, it fails with recursive errors * corefile: Fix stack detection and Mapping.__contains__ logic * corefile: Better detection of AT_EXECFN when NT_AUXV does not have it * corefile: Avoid trying to parse corrupt stacks * Fix doctests for new warning * log: Fix warning_once caching
1 parent 7467402 commit 60df810

File tree

3 files changed

+34
-24
lines changed

3 files changed

+34
-24
lines changed

docs/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ pygments>=2.0
1414
sphinx_rtd_theme
1515
doc2dash
1616
coveralls
17+
sphinx<1.8.0

pwnlib/elf/corefile.py

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
from pwnlib.tubes.ssh import ssh_channel
8888
from pwnlib.tubes.tube import tube
8989
from pwnlib.util.fiddling import b64d
90+
from pwnlib.util.fiddling import enhex
9091
from pwnlib.util.fiddling import unhex
9192
from pwnlib.util.misc import read
9293
from pwnlib.util.misc import write
@@ -223,6 +224,8 @@ def __getitem__(self, item):
223224
return self._core.read(item, 1)
224225

225226
def __contains__(self, item):
227+
if isinstance(item, Mapping):
228+
return (self.start <= item.start) and (item.stop <= self.stop)
226229
return self.start <= item < self.stop
227230

228231
def find(self, sub, start=None, end=None):
@@ -472,6 +475,7 @@ class Corefile(ELF):
472475
>>> io = elf.process()
473476
>>> io.wait()
474477
>>> core = io.corefile
478+
[!] End of the stack is corrupted, skipping stack parsing (got: 4141414141414141)
475479
>>> core.argc, core.argv, core.env
476480
(0, [], {})
477481
>>> core.stack.data.endswith('AAAA')
@@ -545,36 +549,40 @@ def __init__(self, *a, **kw):
545549
for segment in self.segments:
546550
if not isinstance(segment, elftools.elf.segments.NoteSegment):
547551
continue
552+
553+
554+
# Note that older versions of pyelftools (<=0.24) are missing enum values
555+
# for NT_PRSTATUS, NT_PRPSINFO, NT_AUXV, etc.
556+
# For this reason, we have to check if note.n_type is any of several values.
548557
for note in iter_notes(segment):
549-
# Try to find NT_PRSTATUS. Note that pyelftools currently
550-
# mis-identifies the enum name as 'NT_GNU_ABI_TAG'.
558+
# Try to find NT_PRSTATUS.
551559
if prstatus_type and \
552560
note.n_descsz == ctypes.sizeof(prstatus_type) and \
553-
note.n_type == 'NT_GNU_ABI_TAG':
561+
note.n_type in ('NT_GNU_ABI_TAG', 'NT_PRSTATUS'):
554562
self.NT_PRSTATUS = note
555563
self.prstatus = prstatus_type.from_buffer_copy(note.n_desc)
556564

557565
# Try to find NT_PRPSINFO
558-
# Note that pyelftools currently mis-identifies the enum name
559-
# as 'NT_GNU_BUILD_ID'
560-
if note.n_descsz == ctypes.sizeof(prpsinfo_type) and \
561-
note.n_type == 'NT_GNU_BUILD_ID':
566+
if prpsinfo_type and \
567+
note.n_descsz == ctypes.sizeof(prpsinfo_type) and \
568+
note.n_type in ('NT_GNU_ABI_TAG', 'NT_PRPSINFO'):
562569
self.NT_PRPSINFO = note
563570
self.prpsinfo = prpsinfo_type.from_buffer_copy(note.n_desc)
564571

565572
# Try to find NT_SIGINFO so we can see the fault
566-
if note.n_type == 0x53494749:
573+
if note.n_type in (0x53494749, 'NT_SIGINFO'):
567574
self.NT_SIGINFO = note
568575
self.siginfo = siginfo_type.from_buffer_copy(note.n_desc)
569576

570577
# Try to find the list of mapped files
571-
if note.n_type == constants.NT_FILE:
578+
if note.n_type in (constants.NT_FILE, 'NT_FILE'):
572579
with context.local(bytes=self.bytes):
573580
self._parse_nt_file(note)
574581

575582
# Try to find the auxiliary vector, which will tell us
576583
# where the top of the stack is.
577-
if note.n_type == constants.NT_AUXV:
584+
if note.n_type in (constants.NT_AUXV, 'NT_AUXV'):
585+
self.NT_AUXV = note
578586
with context.local(bytes=self.bytes):
579587
self._parse_auxv(note)
580588

@@ -583,19 +591,13 @@ def __init__(self, *a, **kw):
583591

584592
if self.stack and self.mappings:
585593
for mapping in self.mappings:
586-
if mapping.stop == self.stack:
594+
if self.stack in mapping or self.stack == mapping.stop:
587595
mapping.name = '[stack]'
588596
self.stack = mapping
589597
break
590598
else:
591-
for mapping in self.mappings:
592-
if self.stack in mapping:
593-
mapping.name = '[stack]'
594-
self.stack = mapping
595-
break
596-
else:
597-
log.warn('Could not find the stack!')
598-
self.stack = None
599+
log.warn('Could not find the stack!')
600+
self.stack = None
599601

600602
with context.local(bytes=self.bytes, log_level='warn'):
601603
try:
@@ -895,18 +897,25 @@ def _parse_stack(self):
895897
if not stack:
896898
return
897899

900+
# If the stack does not end with zeroes, something is very wrong.
901+
if not stack.data.endswith('\x00' * 8):
902+
log.warn_once("End of the stack is corrupted, skipping stack parsing (got: %s)",
903+
enhex(self.data[-8:]))
904+
return
905+
898906
# AT_EXECFN is the start of the filename, e.g. '/bin/sh'
899907
# Immediately preceding is a NULL-terminated environment variable string.
900908
# We want to find the beginning of it
901-
if self.at_execfn:
902-
address = self.at_execfn-1
903-
else:
904-
log.debug('No AT_EXECFN')
909+
if not self.at_execfn:
905910
address = stack.stop
906911
address -= 2*self.bytes
907912
address -= 1
908913
address = stack.rfind('\x00', None, address)
909914
address += 1
915+
self.at_execfn = address
916+
917+
address = self.at_execfn-1
918+
910919

911920
# Sanity check!
912921
try:

pwnlib/log.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ def warning_once(self, message, *args, **kwargs):
363363
"""
364364
m = message % args
365365
if m not in self._one_time_warnings:
366-
if self.isEnabledFor(logging.INFO):
366+
if self.isEnabledFor(logging.WARNING):
367367
self._one_time_warnings.add(m)
368368
self._log(logging.WARNING, message, args, kwargs, 'warning_once')
369369

0 commit comments

Comments
 (0)