• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Gallopsled / pwntools / 1

11 Jul 2023 10:24PM UTC coverage: 19.327% (-52.2%) from 71.479%
1

push

github

web-flow
shellcraft: more explicit sleep.asm docstring (#2226)

This commit adds information that the sleep shellcraft function does not check if it returned as part of an interrupt and it does not retry the syscall if this occured.

189 of 5940 branches covered (3.18%)

3286 of 17002 relevant lines covered (19.33%)

0.39 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/pwnlib/commandline/shellcraft.py
1
#!/usr/bin/env python2
2
from __future__ import absolute_import
×
3
from __future__ import division
×
4

5
import argparse
×
6
import os
×
7
import six
×
8
import sys
×
9
import types
×
10

11
import pwnlib.args
×
12
pwnlib.args.free_form = False
×
13

14
from pwn import *
×
15
from pwnlib.commandline import common
×
16

17

18
#  ____  _          _ _                 __ _
19
# / ___|| |__   ___| | | ___ _ __ __ _ / _| |_
20
# \___ \| '_ \ / _ \ | |/ __| '__/ _` | |_| __|
21
#  ___) | | | |  __/ | | (__| | | (_| |  _| |_
22
# |____/|_| |_|\___|_|_|\___|_|  \__,_|_|  \__|
23

24
def _string(s):
×
25
    out = []
×
26
    for co in bytearray(s):
×
27
        c = chr(co)
×
28
        if co >= 0x20 and co <= 0x7e and c not in '/$\'"`':
×
29
            out.append(c)
×
30
        else:
31
            out.append('\\x%02x' % co)
×
32
    return '"' + ''.join(out) + '"\n'
×
33

34

35
p = common.parser_commands.add_parser(
×
36
    'shellcraft',
37
    help = 'Microwave shellcode -- Easy, fast and delicious',
38
    description = 'Microwave shellcode -- Easy, fast and delicious',
39
)
40

41

42
p.add_argument(
×
43
    '-?', '--show',
44
    action = 'store_true',
45
    help = 'Show shellcode documentation',
46
)
47

48
p.add_argument(
×
49
    '-o', '--out',
50
    metavar = 'file',
51
    type = argparse.FileType('wb'),
52
    default = getattr(sys.stdout, 'buffer', sys.stdout),
53
    help = 'Output file (default: stdout)',
54
)
55

56
p.add_argument(
×
57
    '-f', '--format',
58
    metavar = 'format',
59
    choices = ['r', 'raw',
60
               's', 'str', 'string',
61
               'c',
62
               'h', 'hex',
63
               'a', 'asm', 'assembly',
64
               'p',
65
               'i', 'hexii',
66
               'e', 'elf',
67
               'd', 'escaped',
68
               'default'],
69
    default = 'default',
70
    help = 'Output format (default: hex), choose from {e}lf, {r}aw, {s}tring, {c}-style array, {h}ex string, hex{i}i, {a}ssembly code, {p}reprocssed code, escape{d} hex string',
71
)
72

73
p.add_argument(
×
74
    'shellcode',
75
    nargs = '?',
76
    help = 'The shellcode you want',
77
    type = str
78
)
79

80
p.add_argument(
×
81
    'args',
82
    nargs = '*',
83
    metavar = 'arg',
84
    default = (),
85
    help = 'Argument to the chosen shellcode',
86
)
87

88
p.add_argument(
×
89
    '-d',
90
    '--debug',
91
    help='Debug the shellcode with GDB',
92
    action='store_true'
93
)
94

95
p.add_argument(
×
96
    '-b',
97
    '--before',
98
    help='Insert a debug trap before the code',
99
    action='store_true'
100
)
101

102
p.add_argument(
×
103
    '-a',
104
    '--after',
105
    help='Insert a debug trap after the code',
106
    action='store_true'
107
)
108

109
p.add_argument(
×
110
    '-v', '--avoid',
111
    action='append',
112
    help = 'Encode the shellcode to avoid the listed bytes'
113
)
114

115
p.add_argument(
×
116
    '-n', '--newline',
117
    dest='avoid',
118
    action='append_const',
119
    const='\n',
120
    help = 'Encode the shellcode to avoid newlines'
121
)
122

123
p.add_argument(
×
124
    '-z', '--zero',
125
    dest='avoid',
126
    action='append_const',
127
    const='\x00',
128
    help = 'Encode the shellcode to avoid NULL bytes'
129
)
130

131
p.add_argument(
×
132
    '-r',
133
    '--run',
134
    help="Run output",
135
    action='store_true'
136
)
137

138
p.add_argument(
×
139
    '--color',
140
    help="Color output",
141
    action='store_true',
142
    default=sys.stdout.isatty()
143
)
144

145
p.add_argument(
×
146
    '--no-color',
147
    help="Disable color output",
148
    action='store_false',
149
    dest='color'
150
)
151

152
p.add_argument(
×
153
    '--syscalls',
154
    help="List syscalls",
155
    action='store_true'
156
)
157

158
p.add_argument(
×
159
    '--address',
160
    help="Load address",
161
    default=None
162
)
163

164
p.add_argument(
×
165
    '-l', '--list',
166
    action='store_true',
167
    help='List available shellcodes, optionally provide a filter'
168
)
169

170
p.add_argument(
×
171
    '-s', '--shared',
172
    action='store_true',
173
    help='Generated ELF is a shared library'
174
)
175

176
def get_template(name):
×
177
    func = shellcraft
×
178
    for attr in name.split('.'):
×
179
        func = getattr(func, attr)
×
180
    return func
×
181

182
def is_not_a_syscall_template(name):
×
183
    template_src = shellcraft._get_source(name)
×
184
    return '/syscalls' not in template_src
×
185

186
def main(args):
×
187
    if args.list:
×
188
        templates = shellcraft.templates
×
189

190
        if args.shellcode:
×
191
            templates = filter(lambda a: args.shellcode in a, templates)
×
192
        elif not args.syscalls:
×
193
            templates = filter(is_not_a_syscall_template, templates)
×
194

195
        print('\n'.join(templates))
×
196
        exit()
×
197

198
    if not args.shellcode:
×
199
        common.parser.print_usage()
×
200
        exit()
×
201

202
    try:
×
203
        func = get_template(args.shellcode)
×
204
    except AttributeError:
×
205
        log.error("Unknown shellcraft template %r. Use --list to see available shellcodes." % args.shellcode)
×
206

207
    if args.show:
×
208
        # remove doctests
209
        doc = []
×
210
        in_doctest = False
×
211
        block_indent = None
×
212
        caption = None
×
213
        lines = func.__doc__.splitlines()
×
214
        i = 0
×
215
        while i < len(lines):
×
216
            line = lines[i]
×
217
            if line.lstrip().startswith('>>>'):
×
218
                # this line starts a doctest
219
                in_doctest = True
×
220
                block_indent = None
×
221
                if caption:
×
222
                    # delete back up to the caption
223
                    doc = doc[:caption - i]
×
224
                    caption = None
×
225
            elif line == '':
×
226
                # skip blank lines
227
                pass
×
228
            elif in_doctest:
×
229
                # indentation marks the end of a doctest
230
                indent = len(line) - len(line.lstrip())
×
231
                if block_indent is None:
×
232
                    if not line.lstrip().startswith('...'):
×
233
                        block_indent = indent
×
234
                elif indent < block_indent:
×
235
                    in_doctest = False
×
236
                    block_indent = None
×
237
                    # re-evalutate this line
238
                    continue
×
239
            elif line.endswith(':'):
×
240
                # save index of caption
241
                caption = i
×
242
            else:
243
                # this is not blank space and we're not in a doctest, so the
244
                # previous caption (if any) was not for a doctest
245
                caption = None
×
246

247
            if not in_doctest:
×
248
                doc.append(line)
×
249
            i += 1
×
250
        print('\n'.join(doc).rstrip())
×
251
        exit()
×
252

253
    defargs = len(six.get_function_defaults(func) or ())
×
254
    reqargs = six.get_function_code(func).co_argcount - defargs
×
255
    if len(args.args) < reqargs:
×
256
        if defargs > 0:
×
257
            log.critical('%s takes at least %d arguments' % (args.shellcode, reqargs))
×
258
            sys.exit(1)
×
259
        else:
260
            log.critical('%s takes exactly %d arguments' % (args.shellcode, reqargs))
×
261
            sys.exit(1)
×
262

263
    # Captain uglyness saves the day!
264
    for i, val in enumerate(args.args):
×
265
        try:
×
266
            args.args[i] = util.safeeval.expr(val)
×
267
        except ValueError:
×
268
            pass
×
269

270
    # And he strikes again!
271
    list(map(common.context_arg, args.shellcode.split('.')))
×
272
    code = func(*args.args)
×
273

274

275
    if args.before:
×
276
        code = shellcraft.trap() + code
×
277
    if args.after:
×
278
        code = code + shellcraft.trap()
×
279

280

281
    if args.format in ['a', 'asm', 'assembly']:
×
282
        if args.color:
×
283
            from pygments import highlight
×
284
            from pygments.formatters import TerminalFormatter
×
285
            from pwnlib.lexer import PwntoolsLexer
×
286

287
            code = highlight(code, PwntoolsLexer(), TerminalFormatter())
×
288

289
        print(code)
×
290
        exit()
×
291
    if args.format == 'p':
×
292
        print(cpp(code))
×
293
        exit()
×
294

295
    assembly = code
×
296

297
    vma = args.address
×
298
    if vma:
×
299
        vma = pwnlib.util.safeeval.expr(vma)
×
300

301
    if args.format in ['e','elf']:
×
302
        args.format = 'default'
×
303
        try: os.fchmod(args.out.fileno(), 0o700)
×
304
        except OSError: pass
×
305

306

307
        if not args.avoid:
×
308
            code = read(make_elf_from_assembly(assembly, vma=vma, shared=args.shared))
×
309
        else:
310
            code = asm(assembly)
×
311
            code = encode(code, args.avoid)
×
312
            code = make_elf(code, vma=vma, shared=args.shared)
×
313
            # code = read(make_elf(encode(asm(code), args.avoid)))
314
    else:
315
        code = encode(asm(assembly), args.avoid)
×
316

317
    if args.format == 'default':
×
318
        if args.out.isatty():
×
319
            args.format = 'hex'
×
320
        else:
321
            args.format = 'raw'
×
322

323
    arch = args.shellcode.split('.')[0]
×
324

325
    if args.debug:
×
326
        if not args.avoid:
×
327
            proc = gdb.debug_assembly(assembly, arch=arch, vma=vma)
×
328
        else:
329
            proc = gdb.debug_shellcode(code, arch=arch, vma=vma)
×
330
        proc.interactive()
×
331
        sys.exit(0)
×
332

333
    if args.run:
×
334
        proc = run_shellcode(code, arch=arch)
×
335
        proc.interactive()
×
336
        sys.exit(0)
×
337

338
    if args.format in ['s', 'str', 'string']:
×
339
        code = _string(code)
×
340
    elif args.format == 'c':
×
341
        code = '{' + ', '.join(map(hex, bytearray(code))) + '}' + '\n'
×
342
    elif args.format in ['h', 'hex']:
×
343
        code = pwnlib.util.fiddling.enhex(code) + '\n'
×
344
    elif args.format in ['i', 'hexii']:
×
345
        code = hexii(code) + '\n'
×
346
    elif args.format in ['d', 'escaped']:
×
347
        code = ''.join('\\x%02x' % c for c in bytearray(code)) + '\n'
×
348
    if not sys.stdin.isatty():
×
349
        args.out.write(getattr(sys.stdin, 'buffer', sys.stdin).read())
×
350

351
    if not hasattr(code, 'decode'):
×
352
        code = code.encode()
×
353
    args.out.write(code)
×
354

355
if __name__ == '__main__':
×
356
    pwnlib.commandline.common.main(__file__)
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc