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

Gallopsled / pwntools / 39eb5b9f9fc3ac2301be5a7a982096b3568d76e1

01 Nov 2023 10:20PM UTC coverage: 73.405% (+1.9%) from 71.525%
39eb5b9f9fc3ac2301be5a7a982096b3568d76e1

push

github-actions

Arusekk
Update CHANGELOG.md

3902 of 6416 branches covered (0.0%)

12255 of 16695 relevant lines covered (73.41%)

0.73 hits per line

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

84.13
/pwnlib/shellcraft/__init__.py
1
from __future__ import absolute_import
1✔
2
from __future__ import division
1✔
3

4
import itertools
1✔
5
import os
1✔
6
import re
1✔
7
import six
1✔
8
import sys
1✔
9
from types import ModuleType
1✔
10

11
from pwnlib import constants
1✔
12
from pwnlib.context import context
1✔
13
from pwnlib.shellcraft import internal
1✔
14
from pwnlib.util import packing
1✔
15

16

17
class module(ModuleType):
1✔
18
    _templates = []
1✔
19

20
    def __init__(self, name, directory):
1✔
21
        super(module, self).__init__(name)
1✔
22

23
        # Insert nice properties
24
        self.__dict__.update({
1✔
25
            '__file__':    __file__,
26
            '__package__': __package__,
27
            '__path__':    __path__,
28
        })
29

30
        # Save the shellcode directory
31
        self._dir = directory
1✔
32

33
        # Find the absolute path of the directory
34
        self._absdir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates', self._dir)
1✔
35

36
        # Get the docstring
37
        with open(os.path.join(self._absdir, "__doc__")) as fd:
1✔
38
            self.__doc__ = fd.read()
1✔
39

40
        # Insert into the module list
41
        sys.modules[self.__name__] = self
1✔
42

43
    def _get_source(self, template):
1✔
44
        assert template in self.templates
1✔
45
        return os.path.join(self._absdir, *template.split('.')) + '.asm'
1✔
46

47
    def __lazyinit__(self):
1✔
48

49
        # Create a dictionary of submodules
50
        self._submodules = {}
1✔
51
        self._shellcodes = {}
1✔
52
        for name in os.listdir(self._absdir):
1✔
53
            path = os.path.join(self._absdir, name)
1✔
54
            if os.path.isdir(path):
1✔
55
                self._submodules[name] = module(self.__name__ + '.' + name, os.path.join(self._dir, name))
1✔
56
            elif os.path.isfile(path) and name != '__doc__' and name[0] != '.':
1✔
57
                funcname, _ext = os.path.splitext(name)
1✔
58
                if not re.match('^[a-zA-Z_][a-zA-Z0-9_]*$', funcname):
1!
59
                    raise ValueError("found illegal filename, %r" % name)
×
60
                self._shellcodes[funcname] = name
1✔
61

62
        # Put the submodules into toplevel
63
        self.__dict__.update(self._submodules)
1✔
64

65
        # These are exported
66
        self.__all__ = sorted(itertools.chain(self._shellcodes.keys(), self._submodules.keys()))
1✔
67

68
        # Make sure this is not called again
69
        self.__lazyinit__ = None
1✔
70

71
    def __getattr__(self, key):
1✔
72
        self.__lazyinit__ and self.__lazyinit__()
1✔
73

74
        # Maybe the lazyinit added it
75
        if key in self.__dict__:
1✔
76
            return self.__dict__[key]
1✔
77

78
        # This function lazy-loads the shellcodes
79
        if key in self._shellcodes:
1✔
80
            real = internal.make_function(key, self._shellcodes[key], self._dir)
1✔
81
            setattr(self, key, real)
1✔
82
            return real
1✔
83

84
        for m in self._context_modules():
1✔
85
            try:
1✔
86
                return getattr(m, key)
1✔
87
            except AttributeError:
1✔
88
                pass
1✔
89

90
        raise AttributeError("'module' object has no attribute '%s'" % key)
1✔
91

92
    def __dir__(self):
1✔
93
        # This function lists the available submodules, available shellcodes
94
        # and potentially shellcodes available in submodules that should be
95
        # avilable because of the context
96
        self.__lazyinit__ and self.__lazyinit__()
×
97

98
        result = list(self._submodules.keys())
×
99
        result.extend(('__file__', '__package__', '__path__',
×
100
                       '__all__',  '__name__'))
101
        result.extend(self.__shellcodes__())
×
102

103
        return result
×
104

105
    def _context_modules(self):
1✔
106
        self.__lazyinit__ and self.__lazyinit__()
1✔
107
        for k, m in self._submodules.items():
1✔
108
            if k in [context.arch, context.os, 'syscalls']:
1✔
109
                yield m
1✔
110

111
    def __shellcodes__(self):
1✔
112
        self.__lazyinit__ and self.__lazyinit__()
×
113
        result = list(self._shellcodes.keys())
×
114
        for m in self._context_modules():
×
115
            result.extend(m.__shellcodes__())
×
116
        return result
×
117

118
    @property
1✔
119
    def templates(self):
120
        if self._templates:
1✔
121
            return self._templates
1✔
122

123
        template_dir = os.path.join(os.path.dirname(__file__), 'templates')
1✔
124
        templates    = []
1✔
125

126
        for root, _, files in os.walk(template_dir, followlinks=True):
1✔
127
            for file in filter(lambda x: x.endswith('.asm'), files):
1✔
128
                value = os.path.splitext(file)[0]
1✔
129
                value = os.path.join(root, value)
1✔
130
                value = value.replace(template_dir, '')
1✔
131
                value = value.replace(os.path.sep, '.')
1✔
132
                value = value.lstrip('.')
1✔
133
                templates.append(value)
1✔
134

135
        templates = sorted(templates)
1✔
136
        self._templates = templates
1✔
137
        return templates
1✔
138

139
    def eval(self, item):
1✔
140
        if isinstance(item, six.integer_types):
1✔
141
            return item
1✔
142
        return constants.eval(item)
1✔
143

144
    def pretty(self, n, comment=True):
1✔
145
        if isinstance(n, (str, bytes, list, tuple, dict)):
1✔
146
            r = repr(n)
1✔
147
            if not comment:  # then it can be inside a comment!
1✔
148
                r = r.replace('*/', r'\x2a/')
1✔
149
            return r
1✔
150
        if not isinstance(n, six.integer_types):
1!
151
            return n
×
152
        if isinstance(n, constants.Constant):
1✔
153
            if comment: return '%s /* %s */' % (n,self.pretty(int(n)))
1✔
154
            else:       return '%s (%s)'     % (n,self.pretty(int(n)))
1✔
155
        elif abs(n) < 10:
1✔
156
            return str(n)
1✔
157
        else:
158
            return hex(n)
1✔
159

160
    def okay(self, s, *a, **kw):
1✔
161
        if isinstance(s, six.integer_types):
1✔
162
            s = packing.pack(s, *a, **kw)
1✔
163
        return b'\0' not in s and b'\n' not in s
1✔
164

165
    from pwnlib.shellcraft import registers
1✔
166

167
# To prevent garbage collection
168
tether = sys.modules[__name__]
1✔
169

170
# Create the module structure
171
shellcraft = module(__name__, '')
1✔
172

173
class LazyImporter:
1✔
174
    def find_module(self, fullname, path=None):
1✔
175
        if not fullname.startswith('pwnlib.shellcraft.'):
1!
176
            return None
1✔
177

178
        parts = fullname.split('.')[2:]
×
179
        cur = shellcraft
×
180
        for part in parts:
×
181
            cur = getattr(cur, part, None)
×
182
            if not isinstance(cur, ModuleType):
×
183
                return None
×
184

185
        return self
×
186

187
    def load_module(self, fullname):
1✔
188
        return sys.modules[fullname]
×
189

190
sys.meta_path.append(LazyImporter())
1✔
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