@@ -136,8 +136,23 @@ def print_binutils_instructions(util, context):
136136%(instructions)s
137137""" .strip () % locals ())
138138
139+
140+ def check_binutils_version (util ):
141+ if util_versions [util ]:
142+ return util_versions [util ]
143+ result = subprocess .check_output ([util , '--version' ,'/dev/null' ],
144+ stderr = subprocess .STDOUT , universal_newlines = True )
145+ if 'clang' in result :
146+ log .warn_once ('Your binutils is clang-based and may not work!\n '
147+ 'Try installing with: https://docs.pwntools.com/en/stable/install/binutils.html\n '
148+ 'Reported version: %r' , result .strip ())
149+ version = re .search (r' (\d+\.\d+)' , result ).group (1 )
150+ util_versions [util ] = version = tuple (map (int , version .split ('.' )))
151+ return version
152+
153+
139154@LocalContext
140- def which_binutils (util ):
155+ def which_binutils (util , check_version = False ):
141156 """
142157 Finds a binutils in the PATH somewhere.
143158 Expects that the utility is prefixed with the architecture name.
@@ -204,17 +219,23 @@ def which_binutils(util):
204219
205220 for pattern in patterns :
206221 for dir in environ ['PATH' ].split (':' ):
207- res = sorted (glob (path .join (dir , pattern )))
208- if res :
209- return res [0 ]
222+ for res in sorted (glob (path .join (dir , pattern ))):
223+ if check_version :
224+ ver = check_binutils_version (res )
225+ return res , ver
226+ return res
210227
211228 # No dice!
212229 print_binutils_instructions (util , context )
213230
214- checked_assembler_version = defaultdict (lambda : False )
231+ util_versions = defaultdict (tuple )
215232
216233def _assembler ():
217- gas = which_binutils ('as' )
234+ gas , version = which_binutils ('as' , check_version = True )
235+ if version < (2 , 19 ):
236+ log .warn_once ('Your binutils version is too old and may not work!\n '
237+ 'Try updating with: https://docs.pwntools.com/en/stable/install/binutils.html\n '
238+ 'Reported version: %r' , version )
218239
219240 E = {
220241 'big' : '-EB' ,
@@ -246,25 +267,10 @@ def _assembler():
246267
247268 assembler = assemblers .get (context .arch , [gas ])
248269
249- if not checked_assembler_version [gas ]:
250- checked_assembler_version [gas ] = True
251- result = subprocess .check_output ([gas , '--version' ,'/dev/null' ],
252- stderr = subprocess .STDOUT , universal_newlines = True )
253- version = re .search (r' (\d+\.\d+)' , result ).group (1 )
254- if 'clang' in result :
255- log .warn_once ('Your binutils is clang version and may not work!\n '
256- 'Try install with: https://docs.pwntools.com/en/stable/install/binutils.html\n '
257- 'Reported Version: %r' , result .strip ())
258- elif version < '2.19' :
259- log .warn_once ('Your binutils version is too old and may not work!\n '
260- 'Try updating with: https://docs.pwntools.com/en/stable/install/binutils.html\n '
261- 'Reported Version: %r' , result .strip ())
262-
263-
264270 return assembler
265271
266272def _linker ():
267- ld = [ which_binutils ('ld' )]
273+ ld , _ = which_binutils ('ld' , check_version = True )
268274 bfd = ['--oformat=' + _bfdname ()]
269275
270276 E = {
@@ -276,7 +282,16 @@ def _linker():
276282 'i386' : ['-m' , 'elf_i386' ],
277283 }.get (context .arch , [])
278284
279- return ld + bfd + [E ] + arguments
285+ return [ld ] + bfd + [E ] + arguments
286+
287+
288+ def _execstack (linker ):
289+ ldflags = ['-z' , 'execstack' ]
290+ version = util_versions [linker [0 ]]
291+ if version >= (2 , 39 ):
292+ return ldflags + ['--no-warn-execstack' , '--no-warn-rwx-segments' ]
293+ return ldflags
294+
280295
281296def _objcopy ():
282297 return [which_binutils ('objcopy' )]
@@ -595,7 +610,7 @@ def make_elf(data,
595610
596611 _run (assembler + ['-o' , step2 , step1 ])
597612
598- linker_options = [ '-z' , 'execstack' ]
613+ linker_options = _execstack ( linker )
599614 if vma is not None :
600615 linker_options += ['--section-start=.shellcode=%#x' % vma ,
601616 '--entry=%#x' % vma ]
@@ -689,7 +704,7 @@ def asm(shellcode, vma = 0, extract = True, shared = False):
689704 shutil .copy (step2 , step3 )
690705
691706 if vma or not extract :
692- ldflags = [ '-z' , 'execstack' , '-o' , step3 , step2 ]
707+ ldflags = _execstack ( linker ) + [ '-o' , step3 , step2 ]
693708 if vma :
694709 ldflags += ['--section-start=.shellcode=%#x' % vma ,
695710 '--entry=%#x' % vma ]
0 commit comments