87
87
from pwnlib .tubes .ssh import ssh_channel
88
88
from pwnlib .tubes .tube import tube
89
89
from pwnlib .util .fiddling import b64d
90
+ from pwnlib .util .fiddling import enhex
90
91
from pwnlib .util .fiddling import unhex
91
92
from pwnlib .util .misc import read
92
93
from pwnlib .util .misc import write
@@ -223,6 +224,8 @@ def __getitem__(self, item):
223
224
return self ._core .read (item , 1 )
224
225
225
226
def __contains__ (self , item ):
227
+ if isinstance (item , Mapping ):
228
+ return (self .start <= item .start ) and (item .stop <= self .stop )
226
229
return self .start <= item < self .stop
227
230
228
231
def find (self , sub , start = None , end = None ):
@@ -472,6 +475,7 @@ class Corefile(ELF):
472
475
>>> io = elf.process()
473
476
>>> io.wait()
474
477
>>> core = io.corefile
478
+ [!] End of the stack is corrupted, skipping stack parsing (got: 4141414141414141)
475
479
>>> core.argc, core.argv, core.env
476
480
(0, [], {})
477
481
>>> core.stack.data.endswith('AAAA')
@@ -545,36 +549,40 @@ def __init__(self, *a, **kw):
545
549
for segment in self .segments :
546
550
if not isinstance (segment , elftools .elf .segments .NoteSegment ):
547
551
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.
548
557
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.
551
559
if prstatus_type and \
552
560
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' ) :
554
562
self .NT_PRSTATUS = note
555
563
self .prstatus = prstatus_type .from_buffer_copy (note .n_desc )
556
564
557
565
# 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' ):
562
569
self .NT_PRPSINFO = note
563
570
self .prpsinfo = prpsinfo_type .from_buffer_copy (note .n_desc )
564
571
565
572
# 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' ) :
567
574
self .NT_SIGINFO = note
568
575
self .siginfo = siginfo_type .from_buffer_copy (note .n_desc )
569
576
570
577
# 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' ) :
572
579
with context .local (bytes = self .bytes ):
573
580
self ._parse_nt_file (note )
574
581
575
582
# Try to find the auxiliary vector, which will tell us
576
583
# 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
578
586
with context .local (bytes = self .bytes ):
579
587
self ._parse_auxv (note )
580
588
@@ -583,19 +591,13 @@ def __init__(self, *a, **kw):
583
591
584
592
if self .stack and self .mappings :
585
593
for mapping in self .mappings :
586
- if mapping . stop == self . stack :
594
+ if self . stack in mapping or self . stack == mapping . stop :
587
595
mapping .name = '[stack]'
588
596
self .stack = mapping
589
597
break
590
598
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
599
601
600
602
with context .local (bytes = self .bytes , log_level = 'warn' ):
601
603
try :
@@ -895,18 +897,25 @@ def _parse_stack(self):
895
897
if not stack :
896
898
return
897
899
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
+
898
906
# AT_EXECFN is the start of the filename, e.g. '/bin/sh'
899
907
# Immediately preceding is a NULL-terminated environment variable string.
900
908
# 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 :
905
910
address = stack .stop
906
911
address -= 2 * self .bytes
907
912
address -= 1
908
913
address = stack .rfind ('\x00 ' , None , address )
909
914
address += 1
915
+ self .at_execfn = address
916
+
917
+ address = self .at_execfn - 1
918
+
910
919
911
920
# Sanity check!
912
921
try :
0 commit comments