Skip to content

Commit 4d600e0

Browse files
committed
Use format strings and raw strings
1 parent a76db16 commit 4d600e0

26 files changed

+121
-122
lines changed

pwnlib/adb/adb.py

+7-7
Original file line numberDiff line numberDiff line change
@@ -887,15 +887,15 @@ def which(name, all = False, *a, **kw):
887887
[]
888888
"""
889889
# Unfortunately, there is no native 'which' on many phones.
890-
which_cmd = '''
890+
which_cmd = fr'''
891891
(IFS=:
892892
for directory in $PATH; do
893893
[ -x "$directory/{name}" ] || continue;
894-
echo -n "$directory/{name}\\x00";
894+
echo -n "$directory/{name}\x00";
895895
done
896896
)
897-
[ -x "{name}" ] && echo -n "$PWD/{name}\\x00"
898-
'''.format(name=name)
897+
[ -x "{name}" ] && echo -n "$PWD/{name}\x00"
898+
'''
899899

900900
which_cmd = which_cmd.strip()
901901
data = process(['sh','-c', which_cmd], *a, **kw).recvall()
@@ -1562,9 +1562,9 @@ def install(apk, *arguments):
15621562
log.error("APK must have .apk extension")
15631563

15641564
basename = os.path.basename(apk)
1565-
target_path = '/data/local/tmp/{}.apk'.format(basename)
1565+
target_path = f'/data/local/tmp/{basename}.apk'
15661566

1567-
with log.progress("Installing APK {}".format(basename)) as p:
1567+
with log.progress(f"Installing APK {basename}") as p:
15681568
with context.quiet:
15691569
p.status('Copying APK to device')
15701570
push(apk, target_path)
@@ -1585,7 +1585,7 @@ def uninstall(package, *arguments):
15851585
package(str): Name of the package to uninstall (e.g. ``'com.foo.MyPackage'``)
15861586
arguments: Supplementary arguments to ``'pm install'``, e.g. ``'-k'``.
15871587
"""
1588-
with log.progress("Uninstalling package {}".format(package)):
1588+
with log.progress(f"Uninstalling package {package}"):
15891589
with context.quiet:
15901590
return process(['pm','uninstall',package] + list(arguments)).recvall()
15911591

pwnlib/asm.py

+7-8
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
from pwnlib.context import LocalContext
6060
from pwnlib.context import context
6161
from pwnlib.log import getLogger
62+
from pwnlib.util.fiddling import hexstr
6263
from pwnlib.util.hashes import sha1sumhex
6364
from pwnlib.util.packing import _encode
6465
from pwnlib.version import __version__
@@ -133,11 +134,10 @@ def print_binutils_instructions(util, context):
133134
if packages:
134135
instructions = '$ sudo apt-get install %s' % packages[0]
135136

136-
log.error("""
137-
Could not find %(util)r installed for %(context)s
137+
log.error(f"""\
138+
Could not find {util!r} installed for {context}
138139
Try installing binutils for this architecture:
139-
%(instructions)s
140-
""".strip() % locals())
140+
{instructions}""")
141141

142142

143143
def check_binutils_version(util):
@@ -624,8 +624,7 @@ def make_elf(data,
624624
assembler = _assembler()
625625
linker = _linker()
626626
code = _arch_header()
627-
code += '.string "%s"' % ''.join('\\x%02x' % c for c in bytearray(data))
628-
code += '\n'
627+
code += f'.string {hexstr(data)}\n'
629628

630629
log.debug("Building ELF:\n" + code)
631630

@@ -693,7 +692,7 @@ def make_macho(data, is_shellcode=False):
693692
if is_shellcode:
694693
code += cpp(data)
695694
else:
696-
code += '.string "%s"' % ''.join('\\x%02x' % c for c in bytearray(data))
695+
code += f'.string {hexstr(data)}\n'
697696

698697
log.debug('Assembling\n%s' % code)
699698

@@ -802,7 +801,7 @@ def asm(shellcode, vma = 0, extract = True, shared = False):
802801
os.makedirs(cache_dir)
803802

804803
# Include the context in the hash in addition to the shellcode
805-
hash_params = '{}_{}_{}_{}'.format(vma, extract, shared, __version__)
804+
hash_params = f'{vma}_{extract}_{shared}_{__version__}'
806805
fingerprint_params = _encode(code) + _encode(hash_params) + _encode(' '.join(assembler)) + _encode(' '.join(linker)) + _encode(' '.join(objcopy))
807806
asm_hash = sha1sumhex(fingerprint_params)
808807
cache_file = os.path.join(cache_dir, asm_hash)

pwnlib/commandline/checksec.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ def main(args):
3636
try:
3737
e = ELF(f)
3838
except Exception as e:
39-
print("{name}: {error}".format(name=f, error=e))
39+
print(f"{f}: {e}")
4040

4141
if __name__ == '__main__':
4242
common.main(__file__, main)

pwnlib/commandline/shellcraft.py

+3-13
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
from pwn import *
1313
from pwnlib.commandline import common
14+
from pwnlib.util.fiddling import hexstr
1415

1516

1617
# ____ _ _ _ __ _
@@ -19,17 +20,6 @@
1920
# ___) | | | | __/ | | (__| | | (_| | _| |_
2021
# |____/|_| |_|\___|_|_|\___|_| \__,_|_| \__|
2122

22-
def _string(s):
23-
out = []
24-
for co in bytearray(s):
25-
c = chr(co)
26-
if co >= 0x20 and co <= 0x7e and c not in '/$\'"`':
27-
out.append(c)
28-
else:
29-
out.append('\\x%02x' % co)
30-
return '"' + ''.join(out) + '"\n'
31-
32-
3323
p = common.parser_commands.add_parser(
3424
'shellcraft',
3525
help = 'Microwave shellcode -- Easy, fast and delicious',
@@ -366,15 +356,15 @@ def main(args):
366356
sys.exit(0)
367357

368358
if args.format in ['s', 'str', 'string']:
369-
code = _string(code)
359+
code = hexstr(code)
370360
elif args.format == 'c':
371361
code = '{' + ', '.join(map(hex, bytearray(code))) + '}' + '\n'
372362
elif args.format in ['h', 'hex']:
373363
code = pwnlib.util.fiddling.enhex(code) + '\n'
374364
elif args.format in ['i', 'hexii']:
375365
code = hexii(code) + '\n'
376366
elif args.format in ['d', 'escaped']:
377-
code = ''.join('\\x%02x' % c for c in bytearray(code)) + '\n'
367+
code = hexstr(code, force=True) + '\n'
378368
if not sys.stdin.isatty():
379369
args.out.write(getattr(sys.stdin, 'buffer', sys.stdin).read())
380370

pwnlib/constants/__init__.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -148,10 +148,10 @@ def eval(self, string):
148148
val = safeeval.values(string, self._env_store[key])
149149

150150
# 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('"#$\',.;@[\\]`{}')):
151+
if set(string) & (set(bytearray(range(32)).decode()) | set(r'"#$\',.;@[]`{}')):
152152
string = val
153153

154-
return Constant('(%s)' % string, val)
154+
return Constant(f'({string})', val)
155155

156156

157157
# To prevent garbage collection

pwnlib/data/includes/generator/load_constants.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939

4040
if paren:
4141
val = '(%s)' % val
42-
print("{key} = Constant({key!r},{val})".format(**locals()), file=python)
42+
print(f"{key} = Constant({key!r},{val})", file=python)
4343
if re.search(r'0o[0-7]', val) or re.match(r'[^0-9a-fA-Fx]0[0-9]', val):
4444
print("#define %s %s" % (key, hex(safeeval.expr(val))), file=header)
4545
else:

pwnlib/data/syscalls/generate.py

+1-6
Original file line numberDiff line numberDiff line change
@@ -239,12 +239,7 @@ def generate_one(target):
239239
string_arguments.append(argname)
240240

241241
argtype = str(arg.type) + ('*' * arg.derefcnt)
242-
arg_docs.append(
243-
' {argname_}({argtype}): {argname}'.format(
244-
argname_=argname_,
245-
argname=argname,
246-
argtype=argtype,
247-
))
242+
arg_docs.append(f' {argname_}({argtype}): {argname}')
248243

249244
# Mako is unable to use *vararg and *kwarg, so we just stub in
250245
# a whole bunch of additional arguments.

pwnlib/data/templates/pwnup.mako

+2-2
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ def start(argv=[], *a, **kw):
155155
# GDB will be launched if the exploit is run via e.g.
156156
# ./exploit.py GDB
157157
%endif
158-
gdbscript = '''
158+
gdbscript = f'''
159159
%if ctx.binary:
160160
%if 'main' in ctx.binary.symbols:
161161
tbreak main
@@ -164,7 +164,7 @@ tbreak *0x{exe.entry:x}
164164
%endif
165165
%endif
166166
continue
167-
'''.format(**locals())
167+
'''
168168
%endif
169169

170170

pwnlib/elf/elf.py

+9-9
Original file line numberDiff line numberDiff line change
@@ -1196,7 +1196,7 @@ def find_ret_main_addr(lines, calls):
11961196
return 0
11971197

11981198
def search(self, needle, writable = False, executable = False):
1199-
"""search(needle, writable = False, executable = False) -> generator
1199+
r"""search(needle, writable = False, executable = False) -> generator
12001200
12011201
Search the ELF's virtual address space for the specified string.
12021202
@@ -1216,7 +1216,7 @@ def search(self, needle, writable = False, executable = False):
12161216
12171217
Examples:
12181218
1219-
An ELF header starts with the bytes ``\\x7fELF``, so we
1219+
An ELF header starts with the bytes ``\x7fELF``, so we
12201220
sould be able to find it easily.
12211221
12221222
>>> bash = ELF('/bin/bash')
@@ -1725,7 +1725,7 @@ def relro(self):
17251725

17261726
@property
17271727
def nx(self):
1728-
""":class:`bool`: Whether the current binary uses NX protections.
1728+
r""":class:`bool`: Whether the current binary uses NX protections.
17291729
17301730
Specifically, we are checking for ``READ_IMPLIES_EXEC`` being set
17311731
by the kernel, as a result of honoring ``PT_GNU_STACK`` in the kernel.
@@ -1788,7 +1788,7 @@ def nx(self):
17881788
| the rest | [#the_rest]_ | exec / non-exec / missing | | enabled |
17891789
+-----------+--------------+---------------------------+------------------------------------------------+----------+
17901790
1791-
\\* Hardware limitations are ignored.
1791+
\* Hardware limitations are ignored.
17921792
17931793
If ``READ_IMPLIES_EXEC`` is set, then `all readable pages are executable`__.
17941794
.. __: https://github.com/torvalds/linux/blob/v6.3/fs/binfmt_elf.c#L1008-L1009
@@ -1802,15 +1802,15 @@ def nx(self):
18021802
18031803
.. code-block:: c
18041804
1805-
#define elf_read_implies_exec(ex, executable_stack) \\
1805+
#define elf_read_implies_exec(ex, executable_stack) \
18061806
(executable_stack != EXSTACK_DISABLE_X)
18071807
18081808
.. [#x86_5.8]
18091809
`source <https://github.com/torvalds/linux/blob/v5.8/arch/x86/include/asm/elf.h#L305-L306>`__
18101810
18111811
.. code-block:: c
18121812
1813-
#define elf_read_implies_exec(ex, executable_stack) \\
1813+
#define elf_read_implies_exec(ex, executable_stack) \
18141814
(mmap_is_ia32() && executable_stack == EXSTACK_DEFAULT)
18151815
18161816
`mmap_is_ia32()`__:
@@ -1889,7 +1889,7 @@ def nx(self):
18891889
18901890
#ifdef __powerpc64__
18911891
/* stripped */
1892-
# define elf_read_implies_exec(ex, exec_stk) (is_32bit_task() ? \\
1892+
# define elf_read_implies_exec(ex, exec_stk) (is_32bit_task() ? \
18931893
(exec_stk == EXSTACK_DEFAULT) : 0)
18941894
#else
18951895
# define elf_read_implies_exec(ex, exec_stk) (exec_stk == EXSTACK_DEFAULT)
@@ -1900,7 +1900,7 @@ def nx(self):
19001900
19011901
.. code-block:: c
19021902
1903-
#define elf_read_implies_exec(ex, executable_stack) \\
1903+
#define elf_read_implies_exec(ex, executable_stack) \
19041904
((executable_stack!=EXSTACK_DISABLE_X) && ((ex).e_flags & EF_IA_64_LINUX_EXECUTABLE_STACK) != 0)
19051905
19061906
EF_IA_64_LINUX_EXECUTABLE_STACK__:
@@ -2153,7 +2153,7 @@ def checksec(self, banner=True, color=True):
21532153
for name, message in sorted(values):
21542154
line = '{} = {}'.format(name, red(str(self.config.get(name, None))))
21552155
if message:
2156-
line += ' ({})'.format(message)
2156+
line += f' ({message})'
21572157
res.append(' ' + line)
21582158

21592159
# res.extend(sorted(config_opts))

pwnlib/encoders/i386/ascii_shellcode.py

+6-7
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,9 @@ def __call__(self, raw_bytes, avoid=None, pcreg=None):
8686
b'Hello world'
8787
"""
8888
if not avoid:
89-
vocab = bytearray(
90-
b"!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~")
89+
vocab = bytes(range(0x21, 0x7f))
9190
else:
92-
required_chars = set('\\-%TXP')
91+
required_chars = set(r'\-%TXP')
9392
allowed = set(all_chars)
9493
if avoid.intersection(required_chars):
9594
raise RuntimeError(
@@ -127,7 +126,7 @@ def _get_allocator(self, size, vocab):
127126
Examples:
128127
129128
>>> context.update(arch='i386', os='linux')
130-
>>> vocab = bytearray(b'!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~')
129+
>>> vocab = bytes(range(0x21, 0x7f))
131130
>>> encoders.i386.ascii_shellcode.encode._get_allocator(300, vocab)
132131
bytearray(b'TX-!!!!-!_``-t~~~P\\%!!!!%@@@@')
133132
"""
@@ -173,7 +172,7 @@ def _find_negatives(self, vocab):
173172
Examples:
174173
175174
>>> context.update(arch='i386', os='linux')
176-
>>> vocab = bytearray(b'!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~')
175+
>>> vocab = bytes(range(0x21, 0x7f))
177176
>>> a, b = encoders.i386.ascii_shellcode.encode._find_negatives(vocab)
178177
>>> a & b
179178
0
@@ -207,7 +206,7 @@ def _get_subtractions(self, shellcode, vocab):
207206
208207
>>> context.update(arch='i386', os='linux')
209208
>>> sc = bytearray(b'ABCDEFGHIGKLMNOPQRSTUVXYZ')
210-
>>> vocab = bytearray(b'!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~')
209+
>>> vocab = bytes(range(0x21, 0x7f))
211210
>>> encoders.i386.ascii_shellcode.encode._get_subtractions(sc, vocab)
212211
bytearray(b'-(!!!-~NNNP-!=;:-f~~~-~~~~P-!!!!-edee-~~~~P-!!!!-eddd-~~~~P-!!!!-egdd-~~~~P-!!!!-eadd-~~~~P-!!!!-eddd-~~~~P')
213212
"""
@@ -250,7 +249,7 @@ def _calc_subtractions(self, last, target, vocab):
250249
Examples:
251250
252251
>>> context.update(arch='i386', os='linux')
253-
>>> vocab = bytearray(b'!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~')
252+
>>> vocab = bytes(range(0x21, 0x7f))
254253
>>> print(encoders.i386.ascii_shellcode.encode._calc_subtractions(bytearray(b'\x10'*4), bytearray(b'\x11'*4), vocab))
255254
[bytearray(b'!!!!'), bytearray(b'`___'), bytearray(b'~~~~')]
256255
>>> print(encoders.i386.ascii_shellcode.encode._calc_subtractions(bytearray(b'\x11\x12\x13\x14'), bytearray(b'\x15\x16\x17\x18'), vocab))

pwnlib/libcdb.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ def provider_libcdb(hex_encoded_id, search_type):
8989
import urllib.parse
9090

9191
# Build the URL using the requested hash type
92-
url_base = "{}/libcdb/libcdb/raw/master/hashes/{}/".format(GITLAB_LIBCDB_URL, search_type)
92+
url_base = f"{GITLAB_LIBCDB_URL}/libcdb/libcdb/raw/master/hashes/{search_type}/"
9393
url = urllib.parse.urljoin(url_base, hex_encoded_id)
9494

9595
data = b""
@@ -114,7 +114,7 @@ def query_libc_rip(params):
114114
# Deferred import because it's slow
115115
import requests
116116

117-
url = "{}/api/find".format(LIBC_RIP_URL)
117+
url = f"{LIBC_RIP_URL}/api/find"
118118
try:
119119
result = requests.post(url, json=params, timeout=20)
120120
result.raise_for_status()
@@ -316,7 +316,7 @@ def _search_debuginfo_by_hash(base_url, hex_encoded_id):
316316
return None
317317

318318
# Try to find separate debuginfo.
319-
url = '/buildid/{}/debuginfo'.format(hex_encoded_id)
319+
url = f'/buildid/{hex_encoded_id}/debuginfo'
320320
url = urllib.parse.urljoin(base_url, url)
321321
data = b""
322322
log.debug("Downloading data from debuginfod: %s", url)
@@ -513,7 +513,7 @@ def _find_libc_package_lib_url(libc):
513513
version = re.search(br'GNU C Library \(Ubuntu E?GLIBC ([^\)]+)\)', libc.data)
514514
if version is not None:
515515
libc_version = version.group(1).decode()
516-
yield 'https://launchpad.net/ubuntu/+archive/primary/+files/libc6_{}_{}.deb'.format(libc_version, libc.arch)
516+
yield f'https://launchpad.net/ubuntu/+archive/primary/+files/libc6_{libc_version}_{libc.arch}.deb'
517517

518518
def download_libraries(libc_path, unstrip=True):
519519
"""download_libraries(str, bool) -> str

pwnlib/memleak.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
__all__ = ['MemLeak', 'RelativeMemLeak']
1616

1717
class MemLeak(object):
18-
"""MemLeak is a caching and heuristic tool for exploiting memory leaks.
18+
r"""MemLeak is a caching and heuristic tool for exploiting memory leaks.
1919
2020
It can be used as a decorator, around functions of the form:
2121
@@ -48,9 +48,9 @@ def some_leaker(addr):
4848
>>> leaker.s(0)[:4]
4949
leaking 0x0
5050
leaking 0x4
51-
b'\\x7fELF'
51+
b'\x7fELF'
5252
>>> leaker[:4]
53-
b'\\x7fELF'
53+
b'\x7fELF'
5454
>>> hex(leaker.d(0))
5555
'0x464c457f'
5656
>>> hex(leaker.clearb(1))

pwnlib/rop/srop.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
1616
Let's just print a message out using SROP.
1717
18-
>>> message = "Hello, World\\n"
18+
>>> message = r"Hello, World\n"
1919
2020
First, we'll create our example binary.
2121
It just reads some data onto the stack, and invokes

0 commit comments

Comments
 (0)