@@ -71,17 +71,9 @@ def _string(s):
7171
7272p .add_argument (
7373 'shellcode' ,
74- nargs = '?' ,
75- help = 'The shellcode you want' ,
76- type = str
77- )
78-
79- p .add_argument (
80- 'args' ,
8174 nargs = '*' ,
82- metavar = 'arg' ,
83- default = (),
84- help = 'Argument to the chosen shellcode' ,
75+ help = 'The shellcodes you want. shellcode [args ...] [+ shellcode [args ...]]' ,
76+ type = str
8577)
8678
8779p .add_argument (
@@ -91,6 +83,12 @@ def _string(s):
9183 action = 'store_true'
9284)
9385
86+ p .add_argument (
87+ '--delim' ,
88+ help = 'Set the delimiter between multilple shellcodes' ,
89+ default = '+'
90+ )
91+
9492p .add_argument (
9593 '-b' ,
9694 '--before' ,
@@ -172,24 +170,50 @@ def _string(s):
172170 help = 'Generated ELF is a shared library'
173171)
174172
175- def get_template (name ):
176- func = shellcraft
177- for attr in name .split ('.' ):
178- func = getattr (func , attr )
179- return func
173+ def get_template (shellcodes ):
174+ funcs = []
175+ for shellcode in shellcodes :
176+ func = shellcraft
177+ cur_name = shellcode [0 ]
178+ args = []
179+ if len (shellcode ) > 1 :
180+ args = shellcode [1 :]
181+ for attr in cur_name .split ('.' ):
182+ func = getattr (func , attr )
183+ funcs .append ((cur_name , func , args ))
184+ return funcs
180185
181186def is_not_a_syscall_template (name ):
182187 template_src = shellcraft ._get_source (name )
183188 return '/syscalls' not in template_src
184189
185190def main (args ):
191+ delim = '+'
192+ if args .delim :
193+ delim = args .delim .strip ()
194+
195+ shellcodes = []
196+ if args .shellcode :
197+ current = []
198+ for s in args .shellcode :
199+ if s .strip () == delim :
200+ shellcodes .append (current )
201+ current = []
202+ else :
203+ current .append (s )
204+ if len (current ) > 0 :
205+ shellcodes .append (current )
206+
186207 if args .list :
187208 templates = shellcraft .templates
188209
189210 if args .shellcode :
190- templates = filter (lambda a : args .shellcode in a , templates )
211+ template_array = []
212+ for s in shellcodes :
213+ template_array .extend (list (filter (lambda a : s [0 ] in a , templates )))
214+ templates = template_array
191215 elif not args .syscalls :
192- templates = filter (is_not_a_syscall_template , templates )
216+ templates = list ( filter (is_not_a_syscall_template , templates ) )
193217
194218 print ('\n ' .join (templates ))
195219 exit ()
@@ -199,84 +223,92 @@ def main(args):
199223 exit ()
200224
201225 try :
202- func = get_template (args . shellcode )
226+ funcs = get_template (shellcodes )
203227 except AttributeError :
204228 log .error ("Unknown shellcraft template %r. Use --list to see available shellcodes." % args .shellcode )
205229
206230 if args .show :
207- # remove doctests
208- doc = []
209- in_doctest = False
210- block_indent = None
211- caption = None
212- lines = func .__doc__ .splitlines ()
213- i = 0
214- while i < len (lines ):
215- line = lines [i ]
216- if line .lstrip ().startswith ('>>>' ):
217- # this line starts a doctest
218- in_doctest = True
219- block_indent = None
220- if caption :
221- # delete back up to the caption
222- doc = doc [:caption - i ]
223- caption = None
224- elif line == '' :
225- # skip blank lines
226- pass
227- elif in_doctest :
228- # indentation marks the end of a doctest
229- indent = len (line ) - len (line .lstrip ())
230- if block_indent is None :
231- if not line .lstrip ().startswith ('...' ):
232- block_indent = indent
233- elif indent < block_indent :
234- in_doctest = False
231+ for (name , func , _args ) in funcs :
232+ # remove doctests
233+ doc = []
234+ in_doctest = False
235+ block_indent = None
236+ caption = None
237+ lines = func .__doc__ .splitlines ()
238+ i = 0
239+ if len (funcs ) > 1 :
240+ print ('%s:' % name )
241+ while i < len (lines ):
242+ line = lines [i ]
243+ if line .lstrip ().startswith ('>>>' ):
244+ # this line starts a doctest
245+ in_doctest = True
235246 block_indent = None
236- # re-evalutate this line
237- continue
238- elif line .endswith (':' ):
239- # save index of caption
240- caption = i
241- else :
242- # this is not blank space and we're not in a doctest, so the
243- # previous caption (if any) was not for a doctest
244- caption = None
245-
246- if not in_doctest :
247- doc .append (line )
248- i += 1
249- print ('\n ' .join (doc ).rstrip ())
247+ if caption :
248+ # delete back up to the caption
249+ doc = doc [:caption - i ]
250+ caption = None
251+ elif line == '' :
252+ # skip blank lines
253+ pass
254+ elif in_doctest :
255+ # indentation marks the end of a doctest
256+ indent = len (line ) - len (line .lstrip ())
257+ if block_indent is None :
258+ if not line .lstrip ().startswith ('...' ):
259+ block_indent = indent
260+ elif indent < block_indent :
261+ in_doctest = False
262+ block_indent = None
263+ # re-evalutate this line
264+ continue
265+ elif line .endswith (':' ):
266+ # save index of caption
267+ caption = i
268+ else :
269+ # this is not blank space and we're not in a doctest, so the
270+ # previous caption (if any) was not for a doctest
271+ caption = None
272+
273+ if not in_doctest :
274+ doc .append (line )
275+ i += 1
276+ print ('\n ' .join (doc ).rstrip ())
277+ if len (funcs ) > 1 :
278+ print ('' )
250279 exit ()
251280
252- defargs = len (six .get_function_defaults (func ) or ())
253- reqargs = six .get_function_code (func ).co_argcount - defargs
254- if len (args .args ) < reqargs :
255- if defargs > 0 :
256- log .critical ('%s takes at least %d arguments' % (args .shellcode , reqargs ))
257- sys .exit (1 )
258- else :
259- log .critical ('%s takes exactly %d arguments' % (args .shellcode , reqargs ))
260- sys .exit (1 )
281+ code_array = []
282+ for (name , func , func_args ) in funcs :
283+ defargs = len (six .get_function_defaults (func ) or ())
284+ reqargs = six .get_function_code (func ).co_argcount - defargs
261285
262- # Captain uglyness saves the day!
263- for i , val in enumerate (args .args ):
264- try :
265- args .args [i ] = util .safeeval .expr (val )
266- except ValueError :
267- pass
286+ if len (func_args ) < reqargs :
287+ if defargs > 0 :
288+ log .critical ('%s takes at least %d arguments' % (name , reqargs ))
289+ sys .exit (1 )
290+ else :
291+ log .critical ('%s takes exactly %d arguments' % (name , reqargs ))
292+ sys .exit (1 )
293+
294+ # Captain uglyness saves the day!
295+ for i , val in enumerate (func_args ):
296+ try :
297+ func_args [i ] = util .safeeval .expr (val )
298+ except ValueError :
299+ pass
268300
269- # And he strikes again!
270- list (map (common .context_arg , args . shellcode .split ('.' )))
271- code = func (* args . args )
301+ # And he strikes again!
302+ list (map (common .context_arg , name .split ('.' )))
303+ code_array . append ( func (* func_args ) )
272304
305+ code = "" .join (code_array )
273306
274307 if args .before :
275308 code = shellcraft .trap () + code
276309 if args .after :
277310 code = code + shellcraft .trap ()
278311
279-
280312 if args .format in ['a' , 'asm' , 'assembly' ]:
281313 if args .color :
282314 from pygments import highlight
@@ -319,7 +351,7 @@ def main(args):
319351 else :
320352 args .format = 'raw'
321353
322- arch = args . shellcode .split ('.' )[0 ]
354+ arch = name .split ('.' )[0 ]
323355
324356 if args .debug :
325357 if not args .avoid :
0 commit comments