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

Gallopsled / pwntools / 3e4e8b70558ee5adb522415f07483b2f72fe0b96

pending completion
3e4e8b70558ee5adb522415f07483b2f72fe0b96

push

github-actions

web-flow
Add `--libc libc.so` argument to pwn template (#2212)

* Add ELF.set_runpath()

Shells out to the `patchelf` tool to patch the ELF's RUNPATH. This lets the dynamic loader look for needed shared libraries in the given path first before the system libraries when running the binary.

* Add ELF.set_interpreter()

Shells out to the `patchelf` tool to patch the ELF's PT_INTERP segment. This allows to change the ld.so used when running the binary.

* Add convenience wrapper to set runpath & interpreter

A helper function to patch the ELF such that it uses the dynamic loader and other libraries in the given folder.

* Add method to download libraries matching a libc

Download the matching libraries for the given libc binary and cache them in a local directory using `libcdb.download_libraries()`. The libraries are looked up using libc.rip and fetched from the official package repositories if available.

Only .deb and .pkg.tar.* packages are currently supported (Debian/Ubuntu, Arch).

* Add --libc argument to pwnup template

This generates code into the template which allows you to run the binary using the given libc.

The foreign libc is used by default, but you can choose to run the binary against your system's local libc using the `LOCAL_LIBC` command line argument when executing the exploit script.

* Work around Python 2 tarfile not supporting xz

* Fix crash when libc wasn't found on libc.rip

* Update README

* Use subprocess.check_output instead of pwnlib.process

* Special case Python 2 instead of 3

* Only catch Exceptions instead of everything

Co-authored-by: Arusekk <arek_koz@o2.pl>

* Check launchpad.net for Ubuntu libcs

This mimics the way io12/pwninit obtains the ld.so.
If the download from libc.rip fails, try launchpad.net.

* Hide comment in template when --quiet

* Please confused pylint in PY2 context

Co-authored-by: Arusekk <arek_koz@o2.pl>

---------

Co-authored-by: Arusekk <arek_koz@o2.pl>

3806 of 6339 branches covered (60.04%)

206 of 206 new or added lines in 3 files covered. (100.0%)

12369 of 16857 relevant lines covered (73.38%)

1.47 hits per line

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

96.15
/pwnlib/util/safeeval.py
1
from __future__ import division
2✔
2

3
_const_codes = [
2✔
4
    'POP_TOP','ROT_TWO','ROT_THREE','ROT_FOUR','DUP_TOP',
5
    'BUILD_LIST','BUILD_MAP','BUILD_TUPLE','BUILD_SET',
6
    'BUILD_CONST_KEY_MAP', 'BUILD_STRING',
7
    'LOAD_CONST','RETURN_VALUE','STORE_SUBSCR', 'STORE_MAP',
8
    'LIST_TO_TUPLE', 'LIST_EXTEND', 'SET_UPDATE', 'DICT_UPDATE', 'DICT_MERGE',
9
    'COPY', 'RESUME',
10
    ]
11

12
_expr_codes = _const_codes + [
2✔
13
    'UNARY_POSITIVE','UNARY_NEGATIVE','UNARY_NOT',
14
    'UNARY_INVERT','BINARY_POWER','BINARY_MULTIPLY',
15
    'BINARY_DIVIDE','BINARY_FLOOR_DIVIDE','BINARY_TRUE_DIVIDE',
16
    'BINARY_MODULO','BINARY_ADD','BINARY_SUBTRACT',
17
    'BINARY_LSHIFT','BINARY_RSHIFT','BINARY_AND','BINARY_XOR',
18
    'BINARY_OR',
19
    'BINARY_OP',
20
    ]
21

22
_values_codes = _expr_codes + ['LOAD_NAME']
2✔
23

24
import six
2✔
25

26
def _get_opcodes(codeobj):
2✔
27
    """_get_opcodes(codeobj) -> [opcodes]
28

29
    Extract the actual opcodes as a list from a code object
30

31
    >>> c = compile("[1 + 2, (1,2)]", "", "eval")
32
    >>> _get_opcodes(c)
33
    [100, 100, 103, 83]
34
    """
35
    import dis
2✔
36
    if hasattr(dis, 'get_instructions'):
2!
37
        return [ins.opcode for ins in dis.get_instructions(codeobj)]
×
38
    i = 0
2✔
39
    opcodes = []
2✔
40
    s = codeobj.co_code
2✔
41
    while i < len(s):
2✔
42
        code = six.indexbytes(s, i)
2✔
43
        opcodes.append(code)
2✔
44
        if code >= dis.HAVE_ARGUMENT:
2✔
45
            i += 3
2✔
46
        else:
47
            i += 1
2✔
48
    return opcodes
2✔
49

50
def test_expr(expr, allowed_codes):
2✔
51
    """test_expr(expr, allowed_codes) -> codeobj
52

53
    Test that the expression contains only the listed opcodes.
54
    If the expression is valid and contains only allowed codes,
55
    return the compiled code object. Otherwise raise a ValueError
56
    """
57
    import dis
2✔
58
    allowed_codes = [dis.opmap[c] for c in allowed_codes if c in dis.opmap]
2✔
59
    try:
2✔
60
        c = compile(expr, "", "eval")
2✔
61
    except SyntaxError:
2✔
62
        raise ValueError("%r is not a valid expression" % expr)
2✔
63
    codes = _get_opcodes(c)
2✔
64
    for code in codes:
2✔
65
        if code not in allowed_codes:
2✔
66
            raise ValueError("opcode %s not allowed" % dis.opname[code])
2✔
67
    return c
2✔
68

69
def const(expr):
2✔
70
    """const(expression) -> value
71

72
    Safe Python constant evaluation
73

74
    Evaluates a string that contains an expression describing
75
    a Python constant. Strings that are not valid Python expressions
76
    or that contain other code besides the constant raise ValueError.
77

78
    Examples:
79

80
        >>> const("10")
81
        10
82
        >>> const("[1,2, (3,4), {'foo':'bar'}]")
83
        [1, 2, (3, 4), {'foo': 'bar'}]
84
        >>> const("[1]+[2]")
85
        Traceback (most recent call last):
86
        ...
87
        ValueError: opcode BINARY_ADD not allowed
88
    """
89

90
    c = test_expr(expr, _const_codes)
2✔
91
    return eval(c)
2✔
92

93
def expr(expr):
2✔
94
    """expr(expression) -> value
95

96
    Safe Python expression evaluation
97

98
    Evaluates a string that contains an expression that only
99
    uses Python constants. This can be used to e.g. evaluate
100
    a numerical expression from an untrusted source.
101

102
    Examples:
103

104
        >>> expr("1+2")
105
        3
106
        >>> expr("[1,2]*2")
107
        [1, 2, 1, 2]
108
        >>> expr("__import__('sys').modules")
109
        Traceback (most recent call last):
110
        ...
111
        ValueError: opcode LOAD_NAME not allowed
112
    """
113

114
    c = test_expr(expr, _expr_codes)
2✔
115
    return eval(c)
2✔
116

117
def values(expr, env):
2✔
118
    """values(expression, dict) -> value
119

120
    Safe Python expression evaluation
121

122
    Evaluates a string that contains an expression that only
123
    uses Python constants and values from a supplied dictionary.
124
    This can be used to e.g. evaluate e.g. an argument to a syscall.
125

126
    Note: This is potentially unsafe if e.g. the __add__ method has side
127
          effects.
128

129
    Examples:
130

131
        >>> values("A + 4", {'A': 6})
132
        10
133
        >>> class Foo:
134
        ...    def __add__(self, other):
135
        ...        print("Firing the missiles")
136
        >>> values("A + 1", {'A': Foo()})
137
        Firing the missiles
138
        >>> values("A.x", {'A': Foo()})
139
        Traceback (most recent call last):
140
        ...
141
        ValueError: opcode LOAD_ATTR not allowed
142
    """
143

144
    # The caller might need his dictionary again
145
    env = dict(env)
2✔
146

147
    # We do not want to have built-ins set
148
    env['__builtins__'] = {}
2✔
149

150
    c = test_expr(expr, _values_codes)
2✔
151
    return eval(c, env)
2✔
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