def __call__(self, raw_bytes, avoid, pcreg=''): while len(raw_bytes) % context.bytes: raw_bytes += '\x00' a, b = xor_pair(raw_bytes, avoid) mov_ecx = shellcraft.i386.mov('ecx', len(raw_bytes) / context.bytes) decoder = self.decoder % mov_ecx decoder = asm(decoder) for left, right in zip(group(context.bytes, a), group(context.bytes, b)): decoder += left decoder += right return decoder
def __call__(self, raw_bytes, avoid, pcreg=''): while len(raw_bytes) % context.bytes: raw_bytes += b'\x00' a, b = xor_pair(raw_bytes, avoid) mov_ecx = shellcraft.i386.mov('ecx', len(raw_bytes) // context.bytes) decoder = self.decoder % mov_ecx decoder = asm(decoder) for left, right in zip(group(context.bytes, a), group(context.bytes, b)): decoder += left decoder += right return decoder
def _write(self, path, data, mode=0o755, timestamp=None, callback=None): if isinstance(path, six.text_type): path = path.encode('utf-8') path += b',%d' % mode self.c.flat32(b'SEND', len(path), path) sent = 0 # Data needs to be broken up into chunks! for chunk in group(0x10000, data): self.c.flat32(b'DATA', len(chunk), chunk) if callback: callback(path, data[:sent], len(data), chunk, len(chunk)) sent += len(chunk) # Send completion notification and timestamp if timestamp is None: timestamp = int(time.time()) self.c.flat32(b'DONE', timestamp) result = self.c.recvn(4) if result != OKAY: log.error("Sync write failed: %r (expected OKAY)" % result) return
def xor_key(data, avoid=b'\x00\n', size=None): r"""xor_key(data, size=None, avoid='\x00\n') -> None or (int, str) Finds a ``size``-width value that can be XORed with a string to produce ``data``, while neither the XOR value or XOR string contain any bytes in ``avoid``. Arguments: data (str): The desired string. avoid: The list of disallowed characters. Defaults to nulls and newlines. size (int): Size of the desired output value, default is word size. Returns: A tuple containing two strings; the XOR key and the XOR string. If no such pair exists, None is returned. Example: >>> xor_key(b"Hello, world") (b'\x01\x01\x01\x01', b'Idmmn-!vnsme') """ size = size or context.bytes if len(data) % size: log.error("Data must be padded to size for xor_key") words = lists.group(size, data) columns = [b''] * size for word in words: for i, byte in enumerate(bytearray(word)): columns[i] += bytearray((byte, )) avoid = bytearray(avoid) alphabet = bytearray(n for n in range(256) if n not in avoid) result = b'' for column in columns: if context.randomize: random.shuffle(alphabet) for c2 in alphabet: if all(c ^ c2 in alphabet for c in column): result += packing._p8lu(c2) break else: return None return result, xor(data, result)
def xor_key(data, avoid='\x00\n', size=None): r"""xor_key(data, size=None, avoid='\x00\n') -> None or (int, str) Finds a ``size``-width value that can be XORed with a string to produce ``data``, while neither the XOR value or XOR string contain any bytes in ``avoid``. Arguments: data (str): The desired string. avoid: The list of disallowed characters. Defaults to nulls and newlines. size (int): Size of the desired output value, default is word size. Returns: A tuple containing two strings; the XOR key and the XOR string. If no such pair exists, None is returned. Example: >>> xor_key("Hello, world") ('\x01\x01\x01\x01', 'Idmmn-!vnsme') """ size = size or context.bytes if len(data) % size: log.error("Data must be padded to size for xor_key") words = lists.group(size, data) columns = [''] * size for word in words: for i,byte in enumerate(word): columns[i] += byte alphabet = list(chr(n) for n in range(256) if chr(n) not in avoid) result = '' for column in columns: if context.randomize: random.shuffle(alphabet) for c2 in alphabet: if all(chr(ord(c)^ord(c2)) in alphabet for c in column): result += c2 break else: return None return result, xor(data, result)
def render_body(context, string, append_null=True, **pageargs): __M_caller = context.caller_stack._push_frame() try: __M_locals = __M_dict_builtin(pageargs=pageargs, string=string, append_null=append_null) repr = context.get('repr', UNDEFINED) __M_writer = context.writer() from pwnlib.shellcraft.thumb import mov __M_locals_builtin_stored = __M_locals_builtin() __M_locals.update( __M_dict_builtin([(__M_key, __M_locals_builtin_stored[__M_key]) for __M_key in ['mov'] if __M_key in __M_locals_builtin_stored])) __M_writer(u'\n') from pwnlib.util import lists, packing __M_locals_builtin_stored = __M_locals_builtin() __M_locals.update( __M_dict_builtin([(__M_key, __M_locals_builtin_stored[__M_key]) for __M_key in ['packing', 'lists'] if __M_key in __M_locals_builtin_stored])) __M_writer(u'\n') __M_writer(u'\n') if append_null: string += '\x00' if not string: return __M_locals_builtin_stored = __M_locals_builtin() __M_locals.update( __M_dict_builtin([(__M_key, __M_locals_builtin_stored[__M_key]) for __M_key in ['string'] if __M_key in __M_locals_builtin_stored])) __M_writer(u' /* push ') __M_writer(unicode(repr(string))) __M_writer(u' */\n\n') for word in lists.group(4, string, 'fill', '\x00')[::-1]: __M_writer(u' ') __M_writer(unicode(mov('r1', packing.unpack(word)))) __M_writer(u'\n push {r1}\n') return '' finally: context.caller_stack._pop_frame()
def _write(self, path, data, mode=0o755, timestamp=None, callback=None): path += ',' + str(mode) self.c.flat('SEND', len(path), path) sent = 0 # Data needs to be broken up into chunks! for chunk in group(0x10000, data): self.c.flat('DATA', len(chunk), chunk) if callback: callback(path, data[:sent], len(data), chunk, len(chunk)) sent += len(chunk) # Send completion notification and timestamp if timestamp is None: timestamp = int(time.time()) self.c.flat('DONE', timestamp) result = self.c.recvn(4) if result != 'OKAY': log.error("Sync write failed: %r (expected OKAY)" % result) return
def _write(self, path, data, mode=0o755, timestamp=None, callback=None): path += ',' + str(mode) self.c.flat32('SEND', len(path), path) sent = 0 # Data needs to be broken up into chunks! for chunk in group(0x10000, data): self.c.flat32('DATA', len(chunk), chunk) if callback: callback(path, data[:sent], len(data), chunk, len(chunk)) sent += len(chunk) # Send completion notification and timestamp if timestamp is None: timestamp = int(time.time()) self.c.flat32('DONE', timestamp) result = self.c.recvn(4) if result != 'OKAY': log.error("Sync write failed: %r (expected OKAY)" % result) return
def build(self, base=None, description=None): """ Construct the ROP chain into a list of elements which can be passed to :func:`.flat`. Arguments: base(int): The base address to build the rop-chain from. Defaults to :attr:`base`. description(dict): Optional output argument, which will gets a mapping of ``address: description`` for each address on the stack, starting at ``base``. """ if base is None: base = self.base or 0 stack = DescriptiveStack(base) chain = self._chain # # First pass # # Get everything onto the stack and save as much descriptive information # as possible. # # The only replacements performed are to add stack adjustment gadgets # (to move SP to the next gadget after a Call) and NextGadgetAddress, # which can only be calculated in this pass. # iterable = enumerate(chain) for idx, slot in iterable: remaining = len(chain) - 1 - idx address = stack.next # Integers can just be added. # Do our best to find out what the address is. if isinstance(slot, six.integer_types): stack.describe(self.describe(slot)) stack.append(slot) # Byte blobs can also be added, however they must be # broken down into pointer-width blobs. elif isinstance(slot, (bytes, six.text_type)): stack.describe(self.describe(slot)) if not isinstance(slot, bytes): slot = slot.encode() slot += self.generatePadding(stack.next, len(slot) % context.bytes) for chunk in lists.group(context.bytes, slot): stack.append(chunk) elif isinstance(slot, srop.SigreturnFrame): stack.describe("Sigreturn Frame") if slot.sp in (0, None) and self.base: slot.sp = stack.next + len(slot) registers = [ slot.registers[i] for i in sorted(slot.registers.keys()) ] for register in registers: value = slot[register] description = self.describe(value) if description: stack.describe('%s = %s' % (register, description)) else: stack.describe('%s' % (register)) stack.append(value) elif isinstance(slot, Call): stack.describe(self.describe(slot)) registers = dict(zip(slot.abi.register_arguments, slot.args)) for value, name in self.setRegisters(registers): if name in registers: index = slot.abi.register_arguments.index(name) description = self.describe(value) or repr(value) stack.describe('[arg%d] %s = %s' % (index, name, description)) elif isinstance(name, Gadget): stack.describe('; '.join(name.insns)) elif isinstance(name, str): stack.describe(name) stack.append(value) if address != stack.next: stack.describe(slot.name) stack.append(slot.target) # For any remaining arguments, put them on the stack stackArguments = slot.args[len(slot.abi.register_arguments):] nextGadgetAddr = stack.next + (context.bytes * len(stackArguments)) # Generally, stack-based arguments assume there's a return # address on the stack. # # We need to at least put padding there so that things line up # properly, but likely also need to adjust the stack past the # arguments. if slot.abi.returns: # Save off the address of the next gadget if remaining or stackArguments: nextGadgetAddr = stack.next # If there were arguments on the stack, we need to stick something # in the slot where the return address goes. if len(stackArguments) > 0: if remaining: fix_size = (1 + len(stackArguments)) fix_bytes = fix_size * context.bytes adjust = self.search(move=fix_bytes) if not adjust: log.error( "Could not find gadget to adjust stack by %#x bytes" % fix_bytes) nextGadgetAddr += adjust.move stack.describe( '<adjust @%#x> %s' % (nextGadgetAddr, self.describe(adjust))) stack.append(adjust.address) for pad in range(fix_bytes, adjust.move, context.bytes): stackArguments.append(Padding()) # We could not find a proper "adjust" gadget, but also didn't need one. else: stack.append(Padding("<return address>")) for i, argument in enumerate(stackArguments): if isinstance(argument, NextGadgetAddress): stack.describe("<next gadget>") stack.append(nextGadgetAddr) else: description = self.describe( argument) or 'arg%i' % (i + len(registers)) stack.describe(description) stack.append(argument) else: stack.append(slot) # # Second pass # # All of the register-loading, stack arguments, and call addresses # are on the stack. We can now start loading in absolute addresses. # start = base end = stack.next size = (stack.next - base) slot_address = base for i, slot in enumerate(stack): if isinstance(slot, six.integer_types): pass elif isinstance(slot, (bytes, six.text_type)): pass elif isinstance(slot, AppendedArgument): stack[i] = stack.next stack.extend( slot.resolve(stack.next + len(slot) - context.bytes)) elif isinstance(slot, CurrentStackPointer): stack[i] = slot_address elif isinstance(slot, Padding): stack[i] = self.generatePadding(i * context.bytes, context.bytes) stack.describe(slot.name, slot_address) elif isinstance(slot, Gadget): stack[i] = slot.address stack.describe(self.describe(slot), slot_address) # Everything else we can just leave in place. # Maybe the user put in something on purpose? # Also, it may work in pwnlib.util.packing.flat() else: pass slot_address += _slot_len(slot) return stack
def render_body(context, string, append_null=True, **pageargs): __M_caller = context.caller_stack._push_frame() try: __M_locals = __M_dict_builtin(pageargs=pageargs, string=string, append_null=append_null) ord = context.get('ord', UNDEFINED) isinstance = context.get('isinstance', UNDEFINED) str = context.get('str', UNDEFINED) __M_writer = context.writer() from pwnlib.util import lists, packing, fiddling from pwnlib.shellcraft import pretty, okay __M_locals_builtin_stored = __M_locals_builtin() __M_locals.update( __M_dict_builtin([ (__M_key, __M_locals_builtin_stored[__M_key]) for __M_key in ['packing', 'fiddling', 'okay', 'pretty', 'lists'] if __M_key in __M_locals_builtin_stored ])) __M_writer(u'\n') __M_writer(u'\n') __M_writer(u'\n') original = string string = packing.flat(string) if append_null: string += '\x00' if isinstance(original, str): original += '\x00' if not string: return if ord(string[-1]) >= 128: extend = '\xff' else: extend = '\x00' __M_locals_builtin_stored = __M_locals_builtin() __M_locals.update( __M_dict_builtin([(__M_key, __M_locals_builtin_stored[__M_key]) for __M_key in ['original', 'extend', 'string'] if __M_key in __M_locals_builtin_stored])) __M_writer(u' /* push ') __M_writer(unicode(pretty(original, False))) __M_writer(u' */\n') for word in lists.group(4, string, 'fill', extend)[::-1]: sign = packing.u32(word, endian='little', sign='signed') __M_locals_builtin_stored = __M_locals_builtin() __M_locals.update( __M_dict_builtin([(__M_key, __M_locals_builtin_stored[__M_key]) for __M_key in ['sign'] if __M_key in __M_locals_builtin_stored])) if sign in [0, 0xa]: __M_writer(u' push ') __M_writer(unicode(pretty(sign + 1))) __M_writer(u'\n dec byte ptr [esp]\n') elif -0x80 <= sign <= 0x7f and okay(word[0]): __M_writer(u' push ') __M_writer(unicode(pretty(sign))) __M_writer(u'\n') elif okay(word): __M_writer(u' push ') __M_writer(unicode(pretty(sign))) __M_writer(u'\n') else: a, b = fiddling.xor_pair(word, avoid='\x00\n') a = packing.u32(a, endian='little', sign='unsigned') b = packing.u32(b, endian='little', sign='unsigned') __M_locals_builtin_stored = __M_locals_builtin() __M_locals.update( __M_dict_builtin([ (__M_key, __M_locals_builtin_stored[__M_key]) for __M_key in ['a', 'b'] if __M_key in __M_locals_builtin_stored ])) __M_writer(u' push ') __M_writer(unicode(pretty(a))) __M_writer(u'\n xor dword ptr [esp], ') __M_writer(unicode(pretty(b))) __M_writer(u'\n') return '' finally: context.caller_stack._pop_frame()
def build(self, base = None, description = None): """ Construct the ROP chain into a list of elements which can be passed to :func:`.flat`. Arguments: base(int): The base address to build the rop-chain from. Defaults to :attr:`base`. description(dict): Optional output argument, which will gets a mapping of ``address: description`` for each address on the stack, starting at ``base``. """ if base is None: base = self.base or 0 stack = DescriptiveStack(base) chain = self._chain # # First pass # # Get everything onto the stack and save as much descriptive information # as possible. # # The only replacements performed are to add stack adjustment gadgets # (to move SP to the next gadget after a Call) and NextGadgetAddress, # which can only be calculated in this pass. # iterable = enumerate(chain) for idx, slot in iterable: remaining = len(chain) - 1 - idx address = stack.next # Integers can just be added. # Do our best to find out what the address is. if isinstance(slot, (int, long)): stack.describe(self.describe(slot)) stack.append(slot) # Byte blobs can also be added, however they must be # broken down into pointer-width blobs. elif isinstance(slot, (str, unicode)): stack.describe(self.describe(slot)) slot += self.generatePadding(stack.next, len(slot) % context.bytes) for chunk in lists.group(context.bytes, slot): stack.append(chunk) elif isinstance(slot, srop.SigreturnFrame): stack.describe("Sigreturn Frame") if slot.sp in (0, None) and self.base: slot.sp = stack.next + len(slot) registers = [slot.registers[i] for i in sorted(slot.registers.keys())] for register in registers: value = slot[register] description = self.describe(value) if description: stack.describe('%s = %s' % (register, description)) else: stack.describe('%s' % (register)) stack.append(value) elif isinstance(slot, Call): stack.describe(self.describe(slot)) registers = dict(zip(slot.abi.register_arguments, slot.args)) setRegisters = self.setRegisters(registers) for register, gadgets in setRegisters.items(): value = registers[register] description = self.describe(value) or 'arg%i' % slot.args.index(value) stack.describe('set %s = %s' % (register, description)) stack.extend(gadgets) if address != stack.next: stack.describe(slot.name) stack.append(slot.target) # For any remaining arguments, put them on the stack stackArguments = slot.args[len(slot.abi.register_arguments):] nextGadgetAddr = stack.next + (context.bytes * len(stackArguments)) # Generally, stack-based arguments assume there's a return # address on the stack. # # We need to at least put padding there so that things line up # properly, but likely also need to adjust the stack past the # arguments. if slot.abi.returns: if remaining: fix_size = (1 + len(stackArguments)) fix_bytes = fix_size * context.bytes adjust = self.search(move = fix_bytes) if not adjust: log.error("Could not find gadget to adjust stack by %#x bytes" % fix_bytes) nextGadgetAddr = stack.next + adjust.move stack.describe('<adjust: %s>' % self.describe(adjust)) stack.append(adjust.address) for pad in range(fix_bytes, adjust.move, context.bytes): stackArguments.append(Padding()) else: stack.describe('<pad>') stack.append(Padding()) for i, argument in enumerate(stackArguments): if isinstance(argument, NextGadgetAddress): stack.describe("<next gadget>") stack.append(nextGadgetAddr) else: description = self.describe(argument) or 'arg%i' % (i + len(registers)) stack.describe(description) stack.append(argument) else: stack.append(slot) # # Second pass # # All of the register-loading, stack arguments, and call addresses # are on the stack. We can now start loading in absolute addresses. # start = base end = stack.next size = (stack.next - base) for i, slot in enumerate(stack): slot_address = stack.address + (i * context.bytes) if isinstance(slot, (int, long)): pass elif isinstance(slot, (str, unicode)): pass elif isinstance(slot, AppendedArgument): stack[i] = stack.next stack.extend(slot.resolve(stack.next)) elif isinstance(slot, CurrentStackPointer): stack[i] = slot_address elif isinstance(slot, Padding): stack[i] = self.generatePadding(i * context.bytes, context.bytes) stack.describe('<pad>', slot_address) elif isinstance(slot, Gadget): stack[i] = slot.address stack.describe(self.describe(slot), slot_address) # Everything else we can just leave in place. # Maybe the user put in something on purpose? # Also, it may work in pwnlib.util.packing.flat() else: pass return stack
def render_body(context,string,append_null=True,**pageargs): __M_caller = context.caller_stack._push_frame() try: __M_locals = __M_dict_builtin(pageargs=pageargs,string=string,append_null=append_null) ord = context.get('ord', UNDEFINED) hex = context.get('hex', UNDEFINED) repr = context.get('repr', UNDEFINED) __M_writer = context.writer() from pwnlib.util import lists, packing, fiddling __M_locals_builtin_stored = __M_locals_builtin() __M_locals.update(__M_dict_builtin([(__M_key, __M_locals_builtin_stored[__M_key]) for __M_key in ['packing','fiddling','lists'] if __M_key in __M_locals_builtin_stored])) __M_writer(u'\n') __M_writer(u'\n') if append_null: string += '\x00' if not string: return def okay(s): return '\n' not in s and '\0' not in s if ord(string[-1]) >= 128: extend = '\xff' else: extend = '\x00' def pretty(n): return hex(n & (2 ** 64 - 1)) __M_locals_builtin_stored = __M_locals_builtin() __M_locals.update(__M_dict_builtin([(__M_key, __M_locals_builtin_stored[__M_key]) for __M_key in ['pretty','okay','string','extend'] if __M_key in __M_locals_builtin_stored])) __M_writer(u' /* push ') __M_writer(unicode(repr(string))) __M_writer(u' */\n') for word in lists.group(8, string, 'fill', extend)[::-1]: sign = packing.u64(word, 'little', 'signed') __M_locals_builtin_stored = __M_locals_builtin() __M_locals.update(__M_dict_builtin([(__M_key, __M_locals_builtin_stored[__M_key]) for __M_key in ['sign'] if __M_key in __M_locals_builtin_stored])) if sign in [0, 0xa]: __M_writer(u' push ') __M_writer(unicode(sign + 1)) __M_writer(u'\n dec byte ptr [rsp]\n') elif -0x80 <= sign <= 0x7f and okay(word[0]): __M_writer(u' push ') __M_writer(unicode(pretty(sign))) __M_writer(u'\n') elif -0x80000000 <= sign <= 0x7fffffff and okay(word[:4]): __M_writer(u' push ') __M_writer(unicode(pretty(sign))) __M_writer(u'\n') elif okay(word): __M_writer(u' mov rax, ') __M_writer(unicode(hex(sign))) __M_writer(u'\n push rax\n') elif word[4:] == '\x00\x00\x00\x00': a,b = fiddling.xor_pair(word[:4], avoid = '\x00\n') a = packing.u32(a, 'little', 'unsigned') b = packing.u32(b, 'little', 'unsigned') __M_locals_builtin_stored = __M_locals_builtin() __M_locals.update(__M_dict_builtin([(__M_key, __M_locals_builtin_stored[__M_key]) for __M_key in ['a','b'] if __M_key in __M_locals_builtin_stored])) __M_writer(u' push ') __M_writer(unicode(pretty(a))) __M_writer(u'\n xor dword ptr [rsp], ') __M_writer(unicode(pretty(b))) __M_writer(u'\n') else: a,b = fiddling.xor_pair(word, avoid = '\x00\n') a = packing.u64(a, 'little', 'unsigned') b = packing.u64(b, 'little', 'unsigned') __M_locals_builtin_stored = __M_locals_builtin() __M_locals.update(__M_dict_builtin([(__M_key, __M_locals_builtin_stored[__M_key]) for __M_key in ['a','b'] if __M_key in __M_locals_builtin_stored])) __M_writer(u' mov rax, ') __M_writer(unicode(pretty(a))) __M_writer(u'\n push rax\n mov rax, ') __M_writer(unicode(pretty(b))) __M_writer(u'\n xor [rsp], rax\n') return '' finally: context.caller_stack._pop_frame()