Exemple #1
0
    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
Exemple #2
0
    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
Exemple #3
0
    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
Exemple #4
0
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)
Exemple #5
0
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)
Exemple #6
0
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()
Exemple #7
0
    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
Exemple #8
0
    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
Exemple #9
0
    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
Exemple #10
0
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()
Exemple #11
0
    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
Exemple #12
0
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()