Skip to content

Commit b76d045

Browse files
committed
Release 4.4.0beta1
2 parents e004aa6 + 957a5a5 commit b76d045

File tree

436 files changed

+925
-883
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

436 files changed

+925
-883
lines changed

CHANGELOG.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ The table below shows which release corresponds to each branch, and what date th
5858

5959
## 4.5.0 (`dev`)
6060

61+
- [#1261][1261] Misc `run_in_new_terminal` improvements (notably gdb terminated by default)
62+
- [#1695][1695] Allow using GDB Python API
63+
64+
[1261]: https://github.com/Gallopsled/pwntools/pull/1261
65+
[1695]: https://github.com/Gallopsled/pwntools/pull/1695
66+
6167
## 4.4.0 (`beta`)
6268

6369
- [#1541][1541] Use `context.newline` for tubes by default
@@ -80,6 +86,7 @@ The table below shows which release corresponds to each branch, and what date th
8086
- [#1688][1688] Add `__setattr__` and `__call__` interfaces to `ROP` for setting registers
8187
- [#1692][1692] Remove python2 shebangs where appropriate
8288
- [#1703][1703] Update libcdb buildid offsets for amd64 and i386
89+
- [#1704][1704] Try https://libc.rip/ for libcdb lookup
8390

8491
[1541]: https://github.com/Gallopsled/pwntools/pull/1541
8592
[1602]: https://github.com/Gallopsled/pwntools/pull/1602
@@ -99,8 +106,15 @@ The table below shows which release corresponds to each branch, and what date th
99106
[1688]: https://github.com/Gallopsled/pwntools/pull/1688
100107
[1692]: https://github.com/Gallopsled/pwntools/pull/1692
101108
[1703]: https://github.com/Gallopsled/pwntools/pull/1703
109+
[1704]: https://github.com/Gallopsled/pwntools/pull/1704
110+
111+
## 4.3.1 (`stable`)
112+
113+
- [#1732][1732] Fix shellcraft SSTI vulnerability (first major pwntools vuln!)
114+
115+
[1732]: https://github.com/Gallopsled/pwntools/pull/1732
102116

103-
## 4.3.0 (`stable`)
117+
## 4.3.0
104118

105119
- [#1576][1576] Add `executable=` argument to `ELF.search`
106120
- [#1584][1584] Add `jmp_esp`/`jmp_rsp` attribute to `ROP`

pwnlib/constants/__init__.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,13 @@ def eval(self, string):
145145
if key not in self._env_store:
146146
self._env_store[key] = {key: getattr(self, key) for key in dir(self) if not key.endswith('__')}
147147

148-
return Constant('(%s)' % string, safeeval.values(string, self._env_store[key]))
148+
val = safeeval.values(string, self._env_store[key])
149+
150+
# if the expression is not assembly-safe, it is not so vital to preserve it
151+
if set(string) & (set(bytearray(range(32)).decode()) | set('"#$\',.;@[\\]`{}')):
152+
string = val
153+
154+
return Constant('(%s)' % string, val)
149155

150156

151157
# To prevent garbage collection

pwnlib/data/syscalls/generate.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#!/usr/bin/env python2
22
from __future__ import division
33
import argparse
4+
import keyword
45
import os
56

67
from pwnlib import constants
@@ -62,7 +63,7 @@
6263
6364
for name, arg in zip(argument_names, argument_values):
6465
if arg is not None:
65-
syscall_repr.append('%s=%r' % (name, arg))
66+
syscall_repr.append('%s=%s' % (name, pwnlib.shellcraft.pretty(arg, False)))
6667
6768
# If the argument itself (input) is a register...
6869
if arg in allregs:
@@ -75,8 +76,8 @@
7576
7677
# The argument is not a register. It is a string value, and we
7778
# are expecting a string value
78-
elif name in can_pushstr and isinstance(arg, (bytes, six.text_type)):
79-
if not isinstance(arg, bytes):
79+
elif name in can_pushstr and isinstance(arg, (six.binary_type, six.text_type)):
80+
if isinstance(arg, six.text_type):
8081
arg = arg.encode('utf-8')
8182
string_arguments[name] = arg
8283
@@ -144,12 +145,11 @@ def can_be_array(arg):
144145

145146

146147
def fix_bad_arg_names(func, arg):
147-
if arg.name == 'str':
148-
return 'str_'
149148
if arg.name == 'len':
150149
return 'length'
151-
if arg.name == 'repr':
152-
return 'repr_'
150+
151+
if arg.name in ('str', 'repr') or keyword.iskeyword(arg.name):
152+
return arg.name + '_'
153153

154154
if func.name == 'open' and arg.name == 'vararg':
155155
return 'mode'
@@ -277,8 +277,10 @@ def generate_one(target):
277277
CALL.format(**template_variables)
278278
]
279279

280-
with open(os.path.join(target, name + '.asm'), 'wt+') as f:
281-
f.write('\n'.join(map(str.strip, lines)))
280+
if keyword.iskeyword(name):
281+
name += '_'
282+
with open(os.path.join(target, name + '.asm'), 'wt') as f:
283+
f.write('\n'.join(map(str.strip, lines)) + '\n')
282284

283285
if __name__ == '__main__':
284286
p = argparse.ArgumentParser()

pwnlib/shellcraft/__init__.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,11 @@ def eval(self, item):
142142
return constants.eval(item)
143143

144144
def pretty(self, n, comment=True):
145-
if isinstance(n, str):
146-
return repr(n)
145+
if isinstance(n, (str, bytes, list, tuple, dict)):
146+
r = repr(n)
147+
if not comment: # then it can be inside a comment!
148+
r = r.replace('*/', r'\x2a/')
149+
return r
147150
if not isinstance(n, six.integer_types):
148151
return n
149152
if isinstance(n, constants.Constant):

pwnlib/shellcraft/templates/aarch64/freebsd/syscall.asm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Example:
3636
if syscall is None:
3737
args = ['?']
3838
else:
39-
args = [repr(syscall)]
39+
args = [pretty(syscall, False)]
4040

4141
for arg in [arg0, arg1, arg2, arg3, arg4, arg5]:
4242
if arg is None:

pwnlib/shellcraft/templates/aarch64/linux/syscall.asm

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<%
2-
from pwnlib.shellcraft import aarch64
2+
from pwnlib.shellcraft import aarch64, pretty
33
from pwnlib.constants import eval
44
from pwnlib.abi import linux_aarch64_syscall as abi
55
from six import text_type
@@ -14,7 +14,7 @@ Any of the arguments can be expressions to be evaluated by :func:`pwnlib.constan
1414
Example:
1515

1616
>>> print(shellcraft.aarch64.linux.syscall(11, 1, 'sp', 2, 0).rstrip())
17-
/* call syscall(11, 1, 'sp', 2, 0) */
17+
/* call syscall(0xb, 1, 'sp', 2, 0) */
1818
mov x0, #1
1919
mov x1, sp
2020
mov x2, #2
@@ -59,13 +59,13 @@ Example:
5959
if syscall is None:
6060
args = ['?']
6161
else:
62-
args = [repr(syscall)]
62+
args = [pretty(syscall, False)]
6363

6464
for arg in [arg0, arg1, arg2, arg3, arg4, arg5]:
6565
if arg is None:
6666
args.append('?')
6767
else:
68-
args.append(repr(arg))
68+
args.append(pretty(arg, False))
6969
while args and args[-1] == '?':
7070
args.pop()
7171
syscall_repr = syscall_repr % ', '.join(args)

pwnlib/shellcraft/templates/aarch64/pushstr_array.asm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ string = b''.join(array)
3939
if len(array) * 8 > 4095:
4040
raise Exception("Array size is too large (%i), max=4095" % len(array))
4141
%>\
42-
/* push argument array ${repr(array)} */
42+
/* push argument array ${shellcraft.pretty(array, False)} */
4343
${shellcraft.pushstr(string, register1=register1, register2=register2)}
4444

4545
/* push null terminator */

pwnlib/shellcraft/templates/amd64/freebsd/syscall.asm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ Example:
7979
if syscall is None:
8080
args = ['?']
8181
else:
82-
args = [repr(syscall)]
82+
args = [pretty(syscall, False)]
8383

8484
for arg in [arg0, arg1, arg2, arg3, arg4, arg5]:
8585
if arg is None:

pwnlib/shellcraft/templates/amd64/linux/syscall.asm

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<%
2-
from pwnlib.shellcraft import amd64
2+
from pwnlib.shellcraft import amd64, pretty
33
from pwnlib.constants import Constant
44
from pwnlib.abi import linux_amd64_syscall as abi
55
from six import text_type
@@ -54,7 +54,7 @@ Example:
5454
... 'PROT_READ | PROT_WRITE | PROT_EXEC',
5555
... 'MAP_PRIVATE | MAP_ANONYMOUS',
5656
... -1, 0).rstrip())
57-
/* call mmap(0, 4096, 'PROT_READ | PROT_WRITE | PROT_EXEC', 'MAP_PRIVATE | MAP_ANONYMOUS', -1, 0) */
57+
/* call mmap(0, 0x1000, 'PROT_READ | PROT_WRITE | PROT_EXEC', 'MAP_PRIVATE | MAP_ANONYMOUS', -1, 0) */
5858
push (MAP_PRIVATE | MAP_ANONYMOUS) /* 0x22 */
5959
pop r10
6060
push -1
@@ -84,6 +84,20 @@ Example:
8484
push SYS_open /* 2 */
8585
pop rax
8686
syscall
87+
>>> print(shellcraft.amd64.write(0, '*/', 2).rstrip())
88+
/* write(fd=0, buf='\x2a/', n=2) */
89+
/* push b'\x2a/\x00' */
90+
push 0x1010101 ^ 0x2f2a
91+
xor dword ptr [rsp], 0x1010101
92+
mov rsi, rsp
93+
xor edi, edi /* 0 */
94+
push 2
95+
pop rdx
96+
/* call write() */
97+
push SYS_write /* 1 */
98+
pop rax
99+
syscall
100+
87101
</%docstring>
88102
<%
89103
append_cdq = False
@@ -95,13 +109,13 @@ Example:
95109
if syscall is None:
96110
args = ['?']
97111
else:
98-
args = [repr(syscall)]
112+
args = [pretty(syscall, False)]
99113

100114
for arg in [arg0, arg1, arg2, arg3, arg4, arg5]:
101115
if arg is None:
102116
args.append('?')
103117
else:
104-
args.append(repr(arg))
118+
args.append(pretty(arg, False))
105119
while args and args[-1] == '?':
106120
args.pop()
107121
syscall_repr = syscall_repr % ', '.join(args)

pwnlib/shellcraft/templates/amd64/push.asm

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<%
22
from pwnlib.util import packing
3-
from pwnlib.shellcraft import amd64
3+
from pwnlib.shellcraft import amd64, pretty
44
from pwnlib.shellcraft.amd64 import pushstr
55
from pwnlib import constants
66
from pwnlib.shellcraft.registers import amd64 as regs
@@ -31,7 +31,7 @@ Example:
3131
/* push 1 */
3232
push 1
3333
>>> print(pwnlib.shellcraft.amd64.push(256).rstrip())
34-
/* push 256 */
34+
/* push 0x100 */
3535
push 0x1010201 ^ 0x100
3636
xor dword ptr [rsp], 0x1010201
3737
>>> with context.local(os = 'linux'):
@@ -58,7 +58,7 @@ Example:
5858
pass
5959
%>
6060
%if not is_reg:
61-
/* push ${repr(value_orig)} */
61+
/* push ${pretty(value_orig, False)} */
6262
${re.sub(r'^\s*/.*\n', '', amd64.pushstr(packing.pack(value), False), 1)}
6363
% else:
6464
push ${value}

0 commit comments

Comments
 (0)