Exemplo n.º 1
0
 def _resolve(self, x):
     if x is None or pwn.isint(x):
         return x
     for y in [self.symbols, self.plt, self.sections]:
         if x in y:
             return y[x]
     return False
Exemplo n.º 2
0
 def __coerce__ (self, other):
     if pwn.isint(other) and self._load_addr:
         return (self._load_addr, other)
     elif isinstance(other, str):
         return (self.flush(), other)
     else:
         pwn.die('Could not coerce ROP.  Other value was: %r' % other)
Exemplo n.º 3
0
 def __coerce__(self, other):
     if pwn.isint(other) and self._load_addr:
         return (self._load_addr, other)
     elif isinstance(other, str):
         return (self.flush(), other)
     else:
         pwn.die('Could not coerce ROP.  Other value was: %r' % other)
Exemplo n.º 4
0
def flat(*args, **kwargs):
    """Flattens the arguments into a string.
Takes a single named argument 'func', which defaults to "p32" if no context is set and to "p" otherwise.
  - Strings are returned
  - Integers are converted using the 'func' argument.
  - Shellcode is assembled
  - Enumerables (such as lists) traversed recursivly and the concatenated.

Example:
  - flat(5, "hello", [[6, "bar"], "baz"]) == '\\x05\\x00\\x00\\x00hello\\x06\\x00\\x00\\x00barbaz'
"""

    global _AssemblerBlock

    if _AssemblerBlock == None:
        from pwn.internal.shellcode_helper import AssemblerBlock as _AssemblerBlock

    if 'arch' in kwargs and kwargs['arch'] != None:
        default_func = p
    else:
        default_func = p32

    func = kwargs.get('func', default_func)

    obj = args[0] if len(args) == 1 else args

    if isinstance(obj, str):
        return obj
    elif pwn.isint(obj):
        return func(obj)
    elif hasattr(obj, '__flat__'):
        return obj.__flat__()
    else:
        return "".join(flat(o, func=func) for o in obj)
Exemplo n.º 5
0
def flat(*args, **kwargs):
    """Flattens the arguments into a string.
Takes a single named argument 'func', which defaults to "p32" if no context is set and to "p" otherwise.
  - Strings are returned
  - Integers are converted using the 'func' argument.
  - Shellcode is assembled
  - Enumerables (such as lists) traversed recursivly and the concatenated.

Example:
  - flat(5, "hello", [[6, "bar"], "baz"]) == '\\x05\\x00\\x00\\x00hello\\x06\\x00\\x00\\x00barbaz'
"""

    global _AssemblerBlock

    if _AssemblerBlock == None:
        from pwn.internal.shellcode_helper import AssemblerBlock as _AssemblerBlock

    if 'arch' in kwargs and kwargs['arch'] != None:
        default_func = p
    else:
        default_func = p32

    func = kwargs.get('func', default_func)

    obj = args[0] if len(args) == 1 else args

    if isinstance(obj, str):
        return obj
    elif pwn.isint(obj):
        return func(obj)
    elif hasattr(obj, '__flat__'):
        return obj.__flat__()
    else:
        return "".join(flat(o, func=func) for o in obj)
Exemplo n.º 6
0
 def _resolve(self, x):
     if x is None or pwn.isint(x):
         return x
     for y in [self.symbols, self.plt, self.sections]:
         if x in y:
             return y[x]
     return self.sections.get('.' + x, False)
Exemplo n.º 7
0
def _mov_thumb(dst, src):
    if not pwn.isint(src):
        return "mov %s, %s" % (dst, src)

    srcu = src & 0xffffffff
    srcs = srcu - 2 * (srcu & 0x80000000)

    if srcu == 0:
        return 'eor %s, %s' % (dst, dst)

    if srcu < 256:
        return 'mov %s, #%d' % (dst, src)

    if -256 < srcs < 0:
        return 'eor %s, %s\nsub %s, #%d' % (dst, dst, dst, -srcs)

    shift1 = 0
    while (1 << shift1) & src == 0:
        shift1 += 1

    if (0xff << shift1) & src == src:
        if shift1 < 4:
            return 'mov %s, #%d\nlsl %s, #4\nlsr %s, #%d' % (
                dst, src >> shift1, dst, dst, 4 - shift1)
        return 'mov %s, #%d\nlsl %s, #%d' % (dst, src >> shift1, dst, shift1)

    shift2 = 8
    while (1 << shift2) & src == 0:
        shift2 += 1

    if ((0xff << shift2) | 0xff) & src == src:
        return 'mov %s, #%d\nlsl %s, #%d\nadd %s, #%d' % (
            dst, src >> shift2, dst, shift2, dst, src & 0xff)

    shift3 = shift1 + 8
    while (1 << shift3) & src == 0:
        shift3 += 1

    if ((0xff << shift1) | (0xff << shift3)) & src == src:
        return 'mov %s, #%d\nlsl %s, #%d\nadd %s, #%d\nlsl %s, #%d' % (
            dst, src >> shift3, dst, shift3 - shift1, dst,
            (src >> shift1) & 0xff, dst, shift1)

    id = pwn.randoms(32, only=string.ascii_lowercase)

    if (src & 0xFF000000 == 0x0):
        src = src | 0xFF000000

        extra = ''.join([
            "lsl %s, #8" % dst,
            "lsr %s, #8" % dst,
        ])

    return '\n'.join([
        "ldr %s, %s" % (dst, id),
        "b %s_after" % id,
        "%s: .word %d" % (id, src),
        "%s_after:" % id, extra
    ])
Exemplo n.º 8
0
def arg_fixup(s):
    if not isinstance(s, str):
        return s
    try:
        import ast
        s2 = ast.literal_eval(s)
        if pwn.isint(s2):
            return s2
    except:
        pass
    try:
        s2 = pwn.clookup(s, eval=True)
        if isinstance(s2, list) and len(s2) == 1 and pwn.isint(s2[0]):
            return s2[0]
    except:
        pass
    return s
Exemplo n.º 9
0
def arg_fixup(s):
    if not isinstance(s, str):
        return s
    try:
        import ast
        s2 = ast.literal_eval(s)
        if pwn.isint(s2):
            return s2
    except:
        pass
    try:
        s2 = pwn.clookup(s, eval = True)
        if isinstance(s2, list) and len(s2) == 1 and pwn.isint(s2[0]):
            return s2[0]
    except:
        pass
    return s
Exemplo n.º 10
0
def _mov_i386(dest, src, stack_allowed):
    regs = [
        ['eax', 'ax', 'al', 'ah'],
        ['ebx', 'bx', 'bl', 'bh'],
        ['ecx', 'cx', 'cl', 'ch'],
        ['edx', 'dx', 'dl', 'dh'],
        ['edi', 'di'],
        ['esi', 'si'],
        ['ebp', 'bp'],
        ['esp', 'sp'],
    ]

    all_regs, sizes, bigger, smaller = _fix_regs(regs, [32, 16, 8, 8])

    if dest not in all_regs:
        bug('%s is not a register' % str(dest))

    if pwn.isint(src):
        if src >= 2**sizes[dest] or src < -(2**(sizes[dest] - 1)):
            pwn.log.warning('Number 0x%x does not fit into %s' % (src, dest))

        srcp = packs_little_endian[sizes[dest]](src)

        if src == 0:
            return 'xor %s, %s' % (dest, dest)

        if '\x00' not in srcp and '\n' not in srcp:
            return 'mov %s, 0x%x' % (dest, src)

        if stack_allowed and sizes[
                dest] == 32 and -128 <= src <= 127 and src != 0xa:
            return 'push 0x%x\npop %s' % (src, dest)

        if stack_allowed and sizes[
                dest] == 16 and -128 <= src <= 127 and src != 0xa:
            return 'push 0x%x\npop %s\ninc esp\ninc esp' % (src, dest)

        a, b = pwn.xor_pair(srcp, avoid='\x00\n')
        u = unpacks_little_endian[sizes[dest]]
        a = u(a)
        b = u(b)
        return 'mov %s, 0x%x\nxor %s, 0x%x' % (dest, a, dest, b)

    elif src in all_regs:
        if src == dest or src in bigger[dest] or src in smaller[dest]:
            return ''
        elif sizes[dest] == sizes[src]:
            return 'mov %s, %s' % (dest, src)
        elif sizes[dest] > sizes[src]:
            return 'movzx %s, %s' % (dest, src)
        else:
            for r in bigger[dest]:
                if sizes[r] == sizes[src]:
                    return 'mov %s, %s' % (r, src)
            bug('Register %s could not be moved into %s' % (src, dest))

    bug('%s is neither a register nor an immediate' % src)
Exemplo n.º 11
0
 def output(xs):
     if doflat:
         return ''.join(chr(x) for x in xs)
     for con in list, tuple:
         if isinstance(args[0], con):
             if all(pwn.isint(x) for x in args[0]):
                 return con(xs)
             else:
                 return con(chr(x) for x in xs)
     return ''.join(chr(x) for x in xs)
Exemplo n.º 12
0
 def output(xs):
     if doflat:
         return ''.join(chr(x) for x in xs)
     for con in list, tuple:
         if isinstance(args[0], con):
             if all(pwn.isint(x) for x in args[0]):
                 return con(xs)
             else:
                 return con(chr(x) for x in xs)
     return ''.join(chr(x) for x in xs)
Exemplo n.º 13
0
def _mov_thumb(dst, src):
    if not pwn.isint(src):
        return "mov %s, %s" % (dst, src)

    srcu = src & 0xffffffff
    srcs = srcu - 2 * (srcu & 0x80000000)

    if srcu == 0:
        return 'eor %s, %s' % (dst, dst)

    if srcu < 256:
        return 'mov %s, #%d' % (dst, src)

    if -256 < srcs < 0:
        return 'eor %s, %s\nsub %s, #%d' % (dst, dst, dst, -srcs)

    shift1 = 0
    while (1 << shift1) & src == 0:
        shift1 += 1

    if (0xff << shift1) & src == src:
        if shift1 < 4:
            return 'mov %s, #%d\nlsl %s, #4\nlsr %s, #%d' % (dst, src >> shift1, dst, dst, 4-shift1)
        return 'mov %s, #%d\nlsl %s, #%d' % (dst, src >> shift1, dst, shift1)

    shift2 = 8
    while (1 << shift2) & src == 0:
        shift2 += 1

    if ((0xff << shift2) | 0xff) & src == src:
        return 'mov %s, #%d\nlsl %s, #%d\nadd %s, #%d' % (dst, src >> shift2, dst, shift2, dst, src & 0xff)

    shift3 = shift1 + 8
    while (1 << shift3) & src == 0:
        shift3 += 1

    if ((0xff << shift1) | (0xff << shift3)) & src == src:
        return 'mov %s, #%d\nlsl %s, #%d\nadd %s, #%d\nlsl %s, #%d' % (dst, src >> shift3, dst, shift3 - shift1, dst, (src >> shift1) & 0xff, dst, shift1)

    id = pwn.randoms(32, only = string.ascii_lowercase)

    if (src & 0xFF000000 == 0x0):
        src = src | 0xFF000000

        extra = ''.join([
        "lsl %s, #8" % dst,
        "lsr %s, #8" % dst,
        ])

    return '\n'.join([
        "ldr %s, %s" % (dst, id),
        "b %s_after" % id,
        "%s: .word %d" % (id, src),
        "%s_after:" % id,
		extra])
Exemplo n.º 14
0
def _mov_i386(dest, src, stack_allowed):
    regs = [['eax', 'ax', 'al', 'ah'],
            ['ebx', 'bx', 'bl', 'bh'],
            ['ecx', 'cx', 'cl', 'ch'],
            ['edx', 'dx', 'dl', 'dh'],
            ['edi', 'di'],
            ['esi', 'si'],
            ['ebp', 'bp'],
            ['esp', 'sp'],
            ]

    all_regs, sizes, bigger, smaller = _fix_regs(regs, [32, 16, 8, 8])

    if dest not in all_regs:
        bug('%s is not a register' % str(dest))

    if pwn.isint(src):
        if src >= 2**sizes[dest] or src < -(2**(sizes[dest]-1)):
            pwn.log.warning('Number 0x%x does not fit into %s' % (src, dest))

        srcp = packs_little_endian[sizes[dest]](src)

        if src == 0:
            return 'xor %s, %s' % (dest, dest)

        if '\x00' not in srcp and '\n' not in srcp:
            return 'mov %s, 0x%x' % (dest, src)

        if stack_allowed and sizes[dest] == 32 and -128 <= src <= 127 and src != 0xa:
            return 'push 0x%x\npop %s' % (src, dest)

        if stack_allowed and sizes[dest] == 16 and -128 <= src <= 127 and src != 0xa:
            return 'push 0x%x\npop %s\ninc esp\ninc esp' % (src, dest)

        a,b = pwn.xor_pair(srcp, avoid = '\x00\n')
        u = unpacks_little_endian[sizes[dest]]
        a = u(a)
        b = u(b)
        return 'mov %s, 0x%x\nxor %s, 0x%x' % (dest, a, dest, b)

    elif src in all_regs:
        if src == dest or src in bigger[dest] or src in smaller[dest]:
            return ''
        elif sizes[dest] == sizes[src]:
            return 'mov %s, %s' % (dest, src)
        elif sizes[dest] > sizes[src]:
            return 'movzx %s, %s' % (dest, src)
        else:
            for r in bigger[dest]:
                if sizes[r] == sizes[src]:
                    return 'mov %s, %s' % (r, src)
            bug('Register %s could not be moved into %s' % (src, dest))

    bug('%s is neither a register nor an immediate' % src)
Exemplo n.º 15
0
def de_bruijn_find(subseq, alphabet = string.ascii_lowercase, n = None):
    """Returns the index for the subsequence of a De Bruijn Sequence for the given alphabet and subsequences of length n. If not specified, n will default to len(subseq).

    There exists better algorithms for this, but they depend on generating the De Bruijn sequence in another fashion. Somebody should look at it:
    http://www.sciencedirect.com/science/article/pii/S0012365X00001175
    """
    if pwn.isint(subseq):
        subseq = pwn.pint(subseq)
    if n == None:
        n = len(subseq)
    return gen_find(subseq, de_bruijn_generator(alphabet, n))
Exemplo n.º 16
0
def xor(*args, **kwargs):
    """Flattens its arguments and then xors them together.
If the end of a string is reached, it wraps around in the string.

Converts the output to a string or a list or tuple of ints or chrs
depending on the first input.

Arguments:
  - func: The function to use with flat. Defaults to p8.
  - cut: How long a string should be returned.
         Can be either 'min'/'max'/'left'/'right' or a number.
  - flat: Ignore type of first argument and flatten output in all
          cases. Defaults to False."""

    if len(args) == 0:
        return []

    cut = kwargs.get('cut', 'max')
    func = kwargs.get('func', p8)
    doflat = kwargs.get('flat', False)

    def output(xs):
        if doflat:
            return ''.join(chr(x) for x in xs)
        for con in list, tuple:
            if isinstance(args[0], con):
                if all(pwn.isint(x) for x in args[0]):
                    return con(xs)
                else:
                    return con(chr(x) for x in xs)
        return ''.join(chr(x) for x in xs)

    strs = filter(len, [map(ord, flat(s, func=func)) for s in args])

    if strs == []:
        return output([])

    if pwn.isint(cut):
        l = cut
    elif cut == 'left':
        l = len(strs[0])
    elif cut == 'right':
        l = len(strs[-1])
    elif cut == 'min':
        l = min(map(len, strs))
    elif cut == 'max':
        l = max(map(len, strs))
    else:
        raise Exception("Not a valid cut argument")

    def get(n):
        return reduce(lambda x, y: x ^ y, [s[n % len(s)] for s in strs])

    return output(get(n) for n in range(l))
Exemplo n.º 17
0
def xor(*args, **kwargs):
    """Flattens its arguments and then xors them together.
If the end of a string is reached, it wraps around in the string.

Converts the output to a string or a list or tuple of ints or chrs
depending on the first input.

Arguments:
  - func: The function to use with flat. Defaults to p8.
  - cut: How long a string should be returned.
         Can be either 'min'/'max'/'left'/'right' or a number.
  - flat: Ignore type of first argument and flatten output in all
          cases. Defaults to False."""

    if len(args) == 0:
        return []

    cut = kwargs.get('cut', 'max')
    func = kwargs.get('func', p8)
    doflat = kwargs.get('flat', False)

    def output(xs):
        if doflat:
            return ''.join(chr(x) for x in xs)
        for con in list, tuple:
            if isinstance(args[0], con):
                if all(pwn.isint(x) for x in args[0]):
                    return con(xs)
                else:
                    return con(chr(x) for x in xs)
        return ''.join(chr(x) for x in xs)

    strs = filter(len, [map(ord, flat(s, func=func)) for s in args])

    if strs == []:
        return output([])

    if pwn.isint(cut):
        l = cut
    elif cut == 'left':
        l = len(strs[0])
    elif cut == 'right':
        l = len(strs[-1])
    elif cut == 'min':
        l = min(map(len, strs))
    elif cut == 'max':
        l = max(map(len, strs))
    else:
        raise Exception("Not a valid cut argument")

    def get(n):
        return reduce(lambda x, y: x ^ y, [s[n % len(s)] for s in strs])

    return output(get(n) for n in range(l))
Exemplo n.º 18
0
    def __len__(self):
        res = 0

        for o in self._content:
            if pwn.isint(o) or _is_sympy(o):
                res += self.wordsize
            elif hasattr(o, '__len__'):
                res += len(o)
            else:
                res += len(pwn.flat(o))

        return res
Exemplo n.º 19
0
    def __len__(self):
        res = 0

        for o in self._content:
            if pwn.isint(o) or _is_sympy(o):
                res += self.wordsize
            elif hasattr(o, '__len__'):
                res += len(o)
            else:
                res += len(pwn.flat(o))

        return res
Exemplo n.º 20
0
 def pargs(args):
     out = []
     for a in args:
         if a is None:
             out.append(garbage())
         elif pwn.isint(a):
             out.append(p(a))
         elif hasattr(a, '__iter__'):
             packed = pargs(a)
             payload.extend(packed)
             out.append(offset[0])
             for a in packed:
                 if pwn.isint(a):
                     offset[0] += 4
                 else:
                     offset[0] += len(a)
         else:
             if isinstance(a, str):
                 a += '\x00'
             a = pwn.flat(a)
             payload.append(a)
             out.append(offset[0])
             offset[0] += len(a)
     return out
Exemplo n.º 21
0
 def pargs(args):
     out = []
     for a in args:
         if   a is None:
             out.append(garbage())
         elif pwn.isint(a):
             out.append(p(a))
         elif hasattr(a, '__iter__'):
             packed = pargs(a)
             payload.extend(packed)
             out.append(offset[0])
             for a in packed:
                 if pwn.isint(a):
                     offset[0] += 4
                 else:
                     offset[0] += len(a)
         else:
             if isinstance(a, str):
                 a += '\x00'
             a = pwn.flat(a)
             payload.append(a)
             out.append(offset[0])
             offset[0] += len(a)
     return out
Exemplo n.º 22
0
 def __setitem__ (self, addr, val):
     import pwn
     if pwn.isint(val):
         if val == 0:
             self.cache[addr] = 0
         else:
             n = 0
             while val:
                 self.cache[addr + n] = val & 0xff
                 val >>= 8
                 n += 1
     elif isinstance(val, str):
         for n, c in enumerate(val):
             self.cache[addr + n] = ord(c)
     else:
         raise TypeError
Exemplo n.º 23
0
    def update_symbols(self, offset = 0, base = None):
        Block.symbols[self.name + '_offset_start'] = offset
        if base:
            Block.symbols[self.name + '_addr_start'] = base + offset

        for o in self._content:
            if isinstance(o, Block):
                offset = o.update_symbols(offset, base)
            elif pwn.isint(o) or _is_sympy(o):
                offset += self.wordsize
            elif hasattr(o, '__len__'):
                offset += len(o)
            else:
                offset += len(pwn.flat(o))
        if base:
            Block.symbols[self.name + '_addr_end'] = base + offset
        Block.symbols[self.name + '_offset_end']   = offset
        Block.symbols[self.name + '_size']  = Block.symbols[self.name + '_offset_end'] - Block.symbols[self.name + '_offset_start']

        return offset
Exemplo n.º 24
0
    def update_symbols(self, offset=0, base=None):
        Block.symbols[self.name + '_offset_start'] = offset
        if base:
            Block.symbols[self.name + '_addr_start'] = base + offset

        for o in self._content:
            if isinstance(o, Block):
                offset = o.update_symbols(offset, base)
            elif pwn.isint(o) or _is_sympy(o):
                offset += self.wordsize
            elif hasattr(o, '__len__'):
                offset += len(o)
            else:
                offset += len(pwn.flat(o))
        if base:
            Block.symbols[self.name + '_addr_end'] = base + offset
        Block.symbols[self.name + '_offset_end'] = offset
        Block.symbols[self.name + '_size'] = Block.symbols[
            self.name + '_offset_end'] - Block.symbols[self.name +
                                                       '_offset_start']

        return offset
Exemplo n.º 25
0
def _mov_arm(dst, src):
    import string

    if not pwn.isint(src):
        return "mov %s, %s" % (dst, src)

    if len(asm("ldr %s, =%d" % (dst, src))) == 4:
        return "ldr %s, =%d" % (dst, src)

    srcu = src & 0xffffffff
    srcn = ~src & 0xffffffff

    for n, op in zip([srcu, srcn], ['mov', 'mvn']):
        shift1 = 0
        while (0x03 << shift1) & n == 0:
            shift1 += 2

        shift2 = shift1 + 8

        while (0x03 << shift2) & n == 0:
            shift2 += 2

        if n == (n & (0xff << shift1)) + (n & (0xff << shift2)):
            return '\n'.join([
                "// mov %s, #%d" % (dst, src),
                "%s %s, #%d" % (op, dst, (n & (0xff << shift1))),
                "%s %s, #%d" % ("eor", dst, (n & (0xff << shift2)))
            ])

    id = pwn.randoms(32, only=string.ascii_lowercase)

    return '\n'.join([
        "ldr %s, %s" % (dst, id),
        "b %s_after" % id,
        "%s: .word %d" % (id, src),
        "%s_after:" % id
    ])
Exemplo n.º 26
0
def _mov_arm(dst, src):
    import string

    if not pwn.isint(src):
        return "mov %s, %s" % (dst, src)

    if len(asm("ldr %s, =%d" % (dst, src))) == 4:
        return "ldr %s, =%d" % (dst, src)

    srcu =  src & 0xffffffff
    srcn = ~src & 0xffffffff

    for n, op in zip([srcu, srcn], ['mov', 'mvn']):
        shift1 = 0
        while (0x03 << shift1) & n == 0:
            shift1 += 2

        shift2 = shift1 + 8

        while (0x03 << shift2) & n == 0:
            shift2 += 2

        if n == (n & (0xff << shift1)) + (n & (0xff << shift2)):
            return '\n'.join([
                "// mov %s, #%d" % (dst, src),
                "%s %s, #%d" % (op,    dst, (n & (0xff << shift1))),
                "%s %s, #%d" % ("eor", dst, (n & (0xff << shift2)))
            ])

    id = pwn.randoms(32, only = string.ascii_lowercase)

    return '\n'.join([
        "ldr %s, %s" % (dst, id),
        "b %s_after" % id,
        "%s: .word %d" % (id, src),
        "%s_after:" % id])
Exemplo n.º 27
0
    def _generate32(self):
        out = []
        chain = self._chain
        self._chain = []
        p = pwn.p32

        def garbage():
            return self._garbage(4)

        payload = []
        offset = [0]

        def pargs(args):
            out = []
            for a in args:
                if a is None:
                    out.append(garbage())
                elif pwn.isint(a):
                    out.append(p(a))
                elif hasattr(a, '__iter__'):
                    packed = pargs(a)
                    payload.extend(packed)
                    out.append(offset[0])
                    for a in packed:
                        if pwn.isint(a):
                            offset[0] += 4
                        else:
                            offset[0] += len(a)
                else:
                    if isinstance(a, str):
                        a += '\x00'
                    a = pwn.flat(a)
                    payload.append(a)
                    out.append(offset[0])
                    offset[0] += len(a)
            return out

        for i in range(len(chain)):
            type, link = chain[i]
            islast = i == len(chain) - 1
            issndlast = i == len(chain) - 2
            if type == 'raw':
                out += pargs(link)
            elif type == 'call':
                target, pivot, args = link
                out.append(p(target))
                if len(args) > 0:
                    if islast:
                        out.append(garbage())
                        out += pargs(args)
                    elif issndlast and chain[i + 1][0] == 'call' and \
                      len(chain[i + 1][1][2]) == 0:
                        # the last target has no arguments, so go straight to it
                        out.append(p(chain[i + 1][1][0]))
                        out += pargs(args)
                        break
                    else:
                        if pivot is None:
                            # find suitable popret
                            res = self._pivot(args)
                            if res is None:
                                pwn.die(
                                    'Could not find gadget for pivoting %d arguments'
                                    % len(args))
                            pivot, size = res
                            args = pargs(args)
                            for _ in range(size - len(args)):
                                args.append(garbage())
                        out.append(p(pivot))
                        out += args
            elif type == 'migrate':
                if not islast:
                    pwn.die('Migrate must be last link in chain')
                esp, ebp = link
                gp = self.gadget('popebp')
                gl = self.gadget('leave')
                if not gp or not gl:
                    pwn.die(
                        'Could not find set-EBP and leave gadgets needed to migrate'
                    )
                if ebp is None:
                    out += [p(gp), p(esp - 4), p(gl)]
                else:
                    out += [p(gp), p(esp), p(gl)]
                    self.raw(ebp)
            else:
                pwn.die('Unknown ROP-link type')
        offset = len(out) * 4
        out_ = out + payload
        out = []
        for o in out_:
            if pwn.isint(o):
                if self._load_addr is None:
                    pwn.die(
                        'Load address of ROP chain not known; can\'t use structures'
                    )
                out.append(p(offset + o + self._load_addr))
            else:
                out.append(o)
        self._load_addr = self._next_load_addr
        self._next_load_addr = None
        return ''.join(out)
Exemplo n.º 28
0
    def _generate32(self):
        out = []
        chain = self._chain
        self._chain = []
        p = pwn.p32
        def garbage():
            return self._garbage(4)

        payload = []
        offset = [0]

        def pargs(args):
            out = []
            for a in args:
                if   a is None:
                    out.append(garbage())
                elif pwn.isint(a):
                    out.append(p(a))
                elif hasattr(a, '__iter__'):
                    packed = pargs(a)
                    payload.extend(packed)
                    out.append(offset[0])
                    for a in packed:
                        if pwn.isint(a):
                            offset[0] += 4
                        else:
                            offset[0] += len(a)
                else:
                    if isinstance(a, str):
                        a += '\x00'
                    a = pwn.flat(a)
                    payload.append(a)
                    out.append(offset[0])
                    offset[0] += len(a)
            return out

        for i in range(len(chain)):
            type, link = chain[i]
            islast = i == len(chain) - 1
            issndlast = i == len(chain) - 2
            if type == 'raw':
                out += pargs(link)
            elif type == 'call':
                target, pivot, args = link
                out.append(p(target))
                if len(args) > 0:
                    if islast:
                        out.append(garbage())
                        out += pargs(args)
                    elif issndlast and chain[i + 1][0] == 'call' and \
                      len(chain[i + 1][1][2]) == 0:
                        # the last target has no arguments, so go straight to it
                        out.append(p(chain[i + 1][1][0]))
                        out += pargs(args)
                        break
                    else:
                        if pivot is None:
                            # find suitable popret
                            res = self._pivot(args)
                            if res is None:
                                pwn.die('Could not find gadget for pivoting %d arguments' % len(args))
                            pivot, size = res
                            args = pargs(args)
                            for _ in range(size - len(args)):
                                args.append(garbage())
                        out.append(p(pivot))
                        out += args
            elif type == 'migrate':
                if not islast:
                    pwn.die('Migrate must be last link in chain')
                esp, ebp = link
                gp = self._gadgets['popebp']
                gl = self._gadgets['leave']
                if len(gp) == 0 and len(gl) == 0:
                    pwn.die('Could not find set-EBP and leave gadgets needed to migrate')
                gp = gp[0]
                gl = gl[0]
                if ebp is None:
                    out += [p(gp), p(esp-4), p(gl)]
                else:
                    out += [p(gp), p(esp), p(gl)]
                    self.raw(ebp)
            else:
                pwn.die('Unknown ROP-link type')
        offset = len(out) * 4
        out_ = out + payload
        out = []
        for o in out_:
            if pwn.isint(o):
                if self._load_addr is None:
                    pwn.die('Load address of ROP chain not known; can\'t use structures')
                out.append(p(offset + o + self._load_addr))
            else:
                out.append(o)
        self._load_addr = self._next_load_addr
        self._next_load_addr = None
        return ''.join(out)
Exemplo n.º 29
0
def _mov_amd64(dest, src, stack_allowed):
    regs = [['rax', 'eax', 'ax', 'al'],
            ['rbx', 'ebx', 'bx', 'bl'],
            ['rcx', 'ecx', 'cx', 'cl'],
            ['rdx', 'edx', 'dx', 'dl'],
            ['rdi', 'edi', 'di', 'dil'],
            ['rsi', 'esi', 'si', 'sil'],
            ['rbp', 'ebp', 'bp', 'bpl'],
            ['rsp', 'esp', 'sp', 'spl'],
            ['r8', 'r8d', 'r8w', 'r8b'],
            ['r9', 'r9d', 'r9w', 'r9b'],
            ['r10', 'r10d', 'r10w', 'r10b'],
            ['r11', 'r11d', 'r11w', 'r11b'],
            ['r12', 'r12d', 'r12w', 'r12b'],
            ['r13', 'r13d', 'r13w', 'r13b'],
            ['r14', 'r14d', 'r14w', 'r14b'],
            ['r15', 'r15d', 'r15w', 'r15b']
            ]

    all_regs, sizes, bigger, smaller = _fix_regs(regs, [64, 32, 16, 8, 8])

    if dest not in all_regs:
        bug('%s is not a register' % str(dest))

    if pwn.isint(src):
        if src >= 2**sizes[dest] or src < -(2**(sizes[dest]-1)):
            pwn.log.warning('Number 0x%x does not fit into %s' % (src, dest))

        srcp = packs_little_endian[sizes[dest]](src)

        if src == 0:
            if sizes[dest] == 64:
                return 'xor %s, %s' % (smaller[dest][0], smaller[dest][0])
            else:
                return 'xor %s, %s' % (dest, dest)

        if '\x00' not in srcp and '\n' not in srcp:
            return 'mov %s, 0x%x' % (dest, src)

        if stack_allowed and sizes[dest] == 64 and -128 <= src <= 127 and src != 0xa:
            return 'push 0x%x\npop %s' % (src, dest)

        # TODO: is it a good idea to transform mov('eax', 17) to mov('rax', 17)
        # automatically?
        if stack_allowed and sizes[dest] == 32 and -128 <= src <= 127 and src != 0xa:
            return 'push 0x%x\npop %s' % (src, bigger[dest][0])

        a,b = pwn.xor_pair(srcp, avoid = '\x00\n')
        u = unpacks_little_endian[sizes[dest]]
        a = u(a)
        b = u(b)
        return 'mov %s, 0x%x\nxor %s, 0x%x' % (dest, a, dest, b)

    elif src in all_regs:
        if src == dest or src in bigger[dest] or src in smaller[dest]:
            return ''
        elif sizes[dest] == sizes[src]:
            return 'mov %s, %s' % (dest, src)
        elif sizes[dest] == 64 and sizes[src] == 32:
            return 'mov %s, %s' % (smaller[dest][0], src)
        elif sizes[dest] > sizes[src]:
            return 'movzx %s, %s' % (dest, src)
        else:
            for r in bigger[dest]:
                if sizes[r] == sizes[src]:
                    return 'mov %s, %s' % (r, src)
            bug('Register %s could not be moved into %s' % (src, dest))

    bug('%s is neither a register nor an immediate' % src)
Exemplo n.º 30
0
def bits(s, endian = 'big', zero = None, one = None, type = None, size = None):
    '''Converts the argument into a string of binary sequence
       or a binary integer list

       Arguments:
         - s: The sequence which should be parsed.
         - endian(optional): The binary endian, default 'big'.
         - zero(optional): The byte representing a 0bit, required if
            one is defined.
         - one(optional): The byte representing a 1bit, required if
            zero is defined.
         - type(optional): A string representing the input type, can be
            'bool' or 'str', defaults to integer if not defined.
         - size: Number of bits to output, None for minimum number of bits.

       Returns a string of 1s and 0s if type = 'str', else a list
         of bits. '''
    types = {bool:     'bool',
             'bool':   'bool',
             str:      'str',
             'str':    'str',
             'string': 'str',
             int:      'int',
             'int':    'int',
             None:     None}

    try:
        type = types[type]
    except:
        pwn.die("Wat. Unknown type %s" % str(type))

    if zero != None or one != None:
        if zero == None or one == None:
            pwn.die("Wat. You cannot specify just a zero or a one in bits")

        if type != None:
            pwn.die("You cannot specify both a type and (zero, one)")
    else:
        if type == 'bool':
            zero = False
            one = True
        elif type == 'str':
            zero = "0"
            one = "1"
        else:
            zero = 0
            one = 1

    out = []
    if isinstance(s, str):
        for c in s:
            b = ord(c)
            byte = []
            for _ in range(8):
                byte.append(one if b & 1 else zero)
                b >>= 1
            if endian == 'little':
                out += byte
            elif endian == 'big':
                out += byte[::-1]
            else:
                pwn.die('Wat (endian style)')
    elif pwn.isint(s):
        while s:
            bit, s = one if s & 1 else zero, s >> 1
            if endian == 'little':
                out.append(bit)
            else:
                out.insert(0, bit)
    else:
        print `s`
        pwn.die("Wat (bits does not support this type)")

    if size is not None:
        if len(out) < size:
            tail = [zero] * (size - len(out))
            if endian == 'little':
                out += tail
            else:
                out = tail + out
        else:
            if endian == 'little':
                out = out[:size]
            else:
                out = out[-size:]

    if type == 'str':
        return ''.join(out)
    else:
        return out
Exemplo n.º 31
0
def enhex(x):
    """Hex-encodes a string or integer"""
    if pwn.isint(x):
        x = pint(x)
    return x.encode('hex')
Exemplo n.º 32
0
def enhex(x):
    """Hex-encodes a string or integer"""
    if pwn.isint(x):
        x = pint(x)
    return x.encode('hex')
Exemplo n.º 33
0
def bits(s, endian='big', zero=None, one=None, type=None, size=None):
    '''Converts the argument into a string of binary sequence
       or a binary integer list

       Arguments:
         - s: The sequence which should be parsed.
         - endian(optional): The binary endian, default 'big'.
         - zero(optional): The byte representing a 0bit, required if
            one is defined.
         - one(optional): The byte representing a 1bit, required if
            zero is defined.
         - type(optional): A string representing the input type, can be
            'bool' or 'str', defaults to integer if not defined.
         - size: Number of bits to output, None for minimum number of bits.

       Returns a string of 1s and 0s if type = 'str', else a list
         of bits. '''
    types = {
        bool: 'bool',
        'bool': 'bool',
        str: 'str',
        'str': 'str',
        'string': 'str',
        int: 'int',
        'int': 'int',
        None: None
    }

    try:
        type = types[type]
    except:
        pwn.die("Wat. Unknown type %s" % str(type))

    if zero != None or one != None:
        if zero == None or one == None:
            pwn.die("Wat. You cannot specify just a zero or a one in bits")

        if type != None:
            pwn.die("You cannot specify both a type and (zero, one)")
    else:
        if type == 'bool':
            zero = False
            one = True
        elif type == 'str':
            zero = "0"
            one = "1"
        else:
            zero = 0
            one = 1

    out = []
    if isinstance(s, str):
        for c in s:
            b = ord(c)
            byte = []
            for _ in range(8):
                byte.append(one if b & 1 else zero)
                b >>= 1
            if endian == 'little':
                out += byte
            elif endian == 'big':
                out += byte[::-1]
            else:
                pwn.die('Wat (endian style)')
    elif pwn.isint(s):
        while s:
            bit, s = one if s & 1 else zero, s >> 1
            if endian == 'little':
                out.append(bit)
            else:
                out.insert(0, bit)
    else:
        print ` s `
        pwn.die("Wat (bits does not support this type)")

    if size is not None:
        if len(out) < size:
            tail = [zero] * (size - len(out))
            if endian == 'little':
                out += tail
            else:
                out = tail + out
        else:
            if endian == 'little':
                out = out[:size]
            else:
                out = out[-size:]

    if type == 'str':
        return ''.join(out)
    else:
        return out
Exemplo n.º 34
0
def _mov_amd64(dest, src, stack_allowed):
    regs = [['rax', 'eax', 'ax', 'al'], ['rbx', 'ebx', 'bx', 'bl'],
            ['rcx', 'ecx', 'cx', 'cl'], ['rdx', 'edx', 'dx', 'dl'],
            ['rdi', 'edi', 'di', 'dil'], ['rsi', 'esi', 'si', 'sil'],
            ['rbp', 'ebp', 'bp', 'bpl'], ['rsp', 'esp', 'sp', 'spl'],
            ['r8', 'r8d', 'r8w', 'r8b'], ['r9', 'r9d', 'r9w', 'r9b'],
            ['r10', 'r10d', 'r10w', 'r10b'], ['r11', 'r11d', 'r11w', 'r11b'],
            ['r12', 'r12d', 'r12w', 'r12b'], ['r13', 'r13d', 'r13w', 'r13b'],
            ['r14', 'r14d', 'r14w', 'r14b'], ['r15', 'r15d', 'r15w', 'r15b']]

    all_regs, sizes, bigger, smaller = _fix_regs(regs, [64, 32, 16, 8, 8])

    if dest not in all_regs:
        bug('%s is not a register' % str(dest))

    if pwn.isint(src):
        if src >= 2**sizes[dest] or src < -(2**(sizes[dest] - 1)):
            pwn.log.warning('Number 0x%x does not fit into %s' % (src, dest))

        srcp = packs_little_endian[sizes[dest]](src)

        if src == 0:
            if sizes[dest] == 64:
                return 'xor %s, %s' % (smaller[dest][0], smaller[dest][0])
            else:
                return 'xor %s, %s' % (dest, dest)

        if '\x00' not in srcp and '\n' not in srcp:
            return 'mov %s, 0x%x' % (dest, src)

        if stack_allowed and sizes[
                dest] == 64 and -128 <= src <= 127 and src != 0xa:
            return 'push 0x%x\npop %s' % (src, dest)

        # TODO: is it a good idea to transform mov('eax', 17) to mov('rax', 17)
        # automatically?
        if stack_allowed and sizes[
                dest] == 32 and -128 <= src <= 127 and src != 0xa:
            return 'push 0x%x\npop %s' % (src, bigger[dest][0])

        a, b = pwn.xor_pair(srcp, avoid='\x00\n')
        u = unpacks_little_endian[sizes[dest]]
        a = u(a)
        b = u(b)
        return 'mov %s, 0x%x\nxor %s, 0x%x' % (dest, a, dest, b)

    elif src in all_regs:
        if src == dest or src in bigger[dest] or src in smaller[dest]:
            return ''
        elif sizes[dest] == sizes[src]:
            return 'mov %s, %s' % (dest, src)
        elif sizes[dest] == 64 and sizes[src] == 32:
            return 'mov %s, %s' % (smaller[dest][0], src)
        elif sizes[dest] > sizes[src]:
            return 'movzx %s, %s' % (dest, src)
        else:
            for r in bigger[dest]:
                if sizes[r] == sizes[src]:
                    return 'mov %s, %s' % (r, src)
            bug('Register %s could not be moved into %s' % (src, dest))

    bug('%s is neither a register nor an immediate' % src)