1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
from __future__ import absolute_import
from __future__ import division
import argparse
import functools
import re
import pwnlib.args
pwnlib.args.free_form = False
from pwn import *
from pwnlib.commandline import common
p = common.parser_commands.add_parser(
'constgrep',
help = "Looking up constants from header files.\n\nExample: constgrep -c freebsd -m ^PROT_ '3 + 4'",
description = "Looking up constants from header files.\n\nExample: constgrep -c freebsd -m ^PROT_ '3 + 4'",
formatter_class = argparse.RawDescriptionHelpFormatter,
)
p.add_argument(
'-e', '--exact',
action='store_true',
help='Do an exact match for a constant instead of searching for a regex',
)
p.add_argument(
'regex',
help='The regex matching constant you want to find',
)
p.add_argument(
'constant',
nargs = '?',
default = None,
type = safeeval.expr,
help = 'The constant to find',
)
p.add_argument(
'-i', '--case-insensitive',
action = 'store_true',
help = 'Search case insensitive',
)
p.add_argument(
'-m', '--mask-mode',
action = 'store_true',
help = 'Instead of searching for a specific constant value, search for values not containing strictly less bits that the given value.',
)
p.add_argument(
'-c', '--context',
metavar = 'arch_or_os',
action = 'append',
type = common.context_arg,
choices = common.choices,
help = 'The os/architecture/endianness/bits the shellcode will run in (default: linux/i386), choose from: %s' % common.choices,
)
def main(args):
if args.exact:
# This is the simple case
print(cpp(args.regex).strip())
else:
# New we search in the right module.
# But first: We find the right module
if context.os == 'freebsd':
mod = constants.freebsd
else:
mod = getattr(getattr(constants, context.os), context.arch)
# Compile the given regex, for optimized lookup
if args.case_insensitive:
matcher = re.compile(args.regex, re.IGNORECASE)
else:
matcher = re.compile(args.regex)
# The found matching constants and the length of the longest string
out = []
maxlen = 0
constant = args.constant
for k in dir(mod):
# No python stuff
if k.endswith('__') and k.startswith('__'):
continue
# Run the regex
if not matcher.search(k):
continue
# Check if the value has proper type
val = getattr(mod, k)
if not isinstance(val, pwnlib.constants.constant.Constant):
continue
# Check the constant
if constant is not None:
if args.mask_mode:
if constant & val != val:
continue
else:
if constant != val:
continue
# Append it
out.append((val, k))
maxlen = max(len(k), maxlen)
# Output all matching constants
for _, k in sorted(out):
print('#define %s %s' % (k.ljust(maxlen), cpp(k).strip()))
# If we are in match_mode, then try to find a combination of
# constants that yield the exact given value
# We do not want to find combinations using the value 0.
if constant and args.mask_mode:
mask = constant
good = []
out = [(v, k) for v, k in out if v != 0]
while mask and out:
cur = out.pop()
mask &= ~cur[0]
good.append(cur)
out = [(v, k) for v, k in out if mask & v == v]
if functools.reduce(lambda x, cur: x | cur[0], good, 0) == constant:
print('')
print('(%s) == %s' % (' | '.join(k for v, k in good), args.constant))
if __name__ == '__main__':
pwnlib.commandline.common.main(__file__, main)
|