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

Gallopsled / pwntools / 5436493948

pending completion
5436493948

push

github-actions

jasperla
add "retguard" property and display it with checksec

quoting http://undeadly.org/cgi?action=article;sid=20180606064444,
retguard is an "anti-ROP security mechanism, which uses random
per-function cookies to protect return addresses on the stack."

3968 of 6663 branches covered (59.55%)

6 of 6 new or added lines in 1 file covered. (100.0%)

12137 of 16984 relevant lines covered (71.46%)

0.71 hits per line

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

49.47
/pwnlib/encoders/encoder.py
1
# -*- coding: utf-8 -*-
2
from __future__ import absolute_import
1✔
3
from __future__ import division
1✔
4

5
import collections
1✔
6
import random
1✔
7
import re
1✔
8
import string
1✔
9

10
from pwnlib.context import LocalContext
1✔
11
from pwnlib.context import context
1✔
12
from pwnlib.log import getLogger
1✔
13
from pwnlib.util.fiddling import hexdump
1✔
14

15
log = getLogger(__name__)
1✔
16

17
class Encoder(object):
1✔
18
    _encoders = collections.defaultdict(lambda: [])
1✔
19

20
    #: Architecture which this encoder works on
21
    arch = None
1✔
22

23
    #: Blacklist of bytes which are known not to be supported
24
    blacklist = set()
1✔
25

26
    def __init__(self):
1✔
27
        """Shellcode encoder class
28

29
        Implements an architecture-specific shellcode encoder
30
        """
31
        Encoder._encoders[self.arch].append(self)
1✔
32

33
    def __call__(self, raw_bytes, avoid, pcreg):
1✔
34
        """avoid(raw_bytes, avoid)
35

36
        Arguments:
37
            raw_bytes(str):
38
                String of bytes to encode
39
            avoid(set):
40
                Set of bytes to avoid
41
            pcreg(str):
42
                Register which contains the address of the shellcode.
43
                May be necessary for some shellcode.
44
        """
45
        raise NotImplementedError()
×
46

47

48
@LocalContext
1✔
49
def encode(raw_bytes, avoid=None, expr=None, force=0, pcreg=''):
1✔
50
    """encode(raw_bytes, avoid, expr, force) -> str
51

52
    Encode shellcode ``raw_bytes`` such that it does not contain
53
    any bytes in ``avoid`` or ``expr``.
54

55
    Arguments:
56

57
        raw_bytes(str): Sequence of shellcode bytes to encode.
58
        avoid(str):     Bytes to avoid
59
        expr(str):      Regular expression which matches bad characters.
60
        force(bool):    Force re-encoding of the shellcode, even if it
61
                        doesn't contain any bytes in ``avoid``.
62
    """
63
    orig_avoid = avoid
1✔
64

65
    avoid = set(avoid or '')
1✔
66

67
    if expr:
1!
68
        for char in all_chars:
×
69
            if re.search(expr, char):
×
70
                avoid.add(char)
×
71

72
    if not (force or avoid & set(raw_bytes)):
1!
73
        return raw_bytes
1✔
74

75
    encoders = Encoder._encoders[context.arch]
×
76
    random.shuffle(encoders)
×
77

78
    for encoder in encoders:
×
79
        if encoder.blacklist & avoid:
×
80
            continue
×
81

82
        try:
×
83
            v = encoder(raw_bytes, bytes(avoid), pcreg)
×
84
        except NotImplementedError:
×
85
            continue
×
86

87
        if avoid & set(v):
×
88
            log.warning_once("Encoder %s did not succeed" % encoder)
×
89
            continue
×
90

91
        return v
×
92

93

94
    avoid_errmsg = ''
×
95
    if orig_avoid and expr:
×
96
        avoid_errmsg = '%r and %r' % (orig_avoid, expr)
×
97
    elif expr:
×
98
        avoid_errmsg = repr(expr)
×
99
    else:
100
        avoid_errmsg = repr(bytes(avoid))
×
101

102
    args = (context.arch, avoid_errmsg, hexdump(raw_bytes))
×
103
    msg = "No encoders for %s which can avoid %s for\n%s" % args
×
104
    msg = msg.replace('%', '%%')
×
105
    log.error(msg)
×
106

107
all_chars        = list(chr(i) for i in range(256))
1✔
108
re_alphanumeric  = r'[^A-Za-z0-9]'
1✔
109
re_printable     = r'[^\x21-\x7e]'
1✔
110
re_whitespace    = r'\s'
1✔
111
re_null          = r'\x00'
1✔
112
re_line          = r'[\s\x00]'
1✔
113

114
@LocalContext
1✔
115
def null(raw_bytes, *a, **kw):
1✔
116
    """null(raw_bytes) -> str
117

118
    Encode the shellcode ``raw_bytes`` such that it does not
119
    contain any NULL bytes.
120

121
    Accepts the same arguments as :func:`encode`.
122
    """
123
    return encode(raw_bytes, expr=re_null, *a, **kw)
×
124

125
@LocalContext
1✔
126
def line(raw_bytes, *a, **kw):
1✔
127
    """line(raw_bytes) -> str
128

129
    Encode the shellcode ``raw_bytes`` such that it does not
130
    contain any NULL bytes or whitespace.
131

132
    Accepts the same arguments as :func:`encode`.
133
    """
134
    return encode(raw_bytes, expr=re_whitespace, *a, **kw)
×
135

136
@LocalContext
1✔
137
def alphanumeric(raw_bytes, *a, **kw):
1✔
138
    """alphanumeric(raw_bytes) -> str
139

140
    Encode the shellcode ``raw_bytes`` such that it does not
141
    contain any bytes except for [A-Za-z0-9].
142

143
    Accepts the same arguments as :func:`encode`.
144
    """
145
    return encode(raw_bytes, expr=re_alphanumeric, *a, **kw)
×
146

147
@LocalContext
1✔
148
def printable(raw_bytes, *a, **kw):
1✔
149
    """printable(raw_bytes) -> str
150

151
    Encode the shellcode ``raw_bytes`` such that it only contains
152
    non-space printable bytes.
153

154
    Accepts the same arguments as :func:`encode`.
155
    """
156
    return encode(raw_bytes, expr=re_printable, *a, **kw)
×
157

158
@LocalContext
1✔
159
def scramble(raw_bytes, *a, **kw):
1✔
160
    """scramble(raw_bytes) -> str
161

162
    Encodes the input data with a random encoder.
163

164
    Accepts the same arguments as :func:`encode`.
165
    """
166
    return encode(raw_bytes, force=1, *a, **kw)
×
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

© 2025 Coveralls, Inc