def _get_subtractions(self, shellcode, vocab): r""" Covert the sellcode to sub eax and posh eax instructions int_size is taken from the context Args: shellcode (bytearray): The shellcode to pack vocab (bytearray): Allowed characters Returns: bytearray: packed shellcode Examples: >>> context.update(arch='i386', os='linux') >>> sc = bytearray(b'ABCDEFGHIGKLMNOPQRSTUVXYZ') >>> vocab = bytearray(b'!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~') >>> encoders.i386.ascii_shellcode.encode._get_subtractions(sc, vocab) bytearray(b'-(!!!-~NNNP-!=;:-f~~~-~~~~P-!!!!-edee-~~~~P-!!!!-eddd-~~~~P-!!!!-egdd-~~~~P-!!!!-eadd-~~~~P-!!!!-eddd-~~~~P') """ int_size = context.bytes result = bytearray() last = bytearray(int_size) # Group the shellcode into bytes of stack cell size, pad with NOPs # if the shellcode does not divide into stack cell size and reverse. # The shellcode will be reversed again back to it's original order once # it's pushed onto the stack sc = tuple(group(int_size, shellcode, 0x90))[::-1] # Pack the shellcode to a sub/push sequence for x in sc: for subtraction in self._calc_subtractions(last, x, vocab): result += b'-' + subtraction # sub eax, ... last = x result += b'P' # push eax return result
def js_escape(data, padding=context.cyclic_alphabet[0:1], **kwargs): r"""js_escape(data, padding=context.cyclic_alphabet[0:1], endian = None, **kwargs) -> str Pack data as an escaped Unicode string for use in JavaScript's `unescape()` function Arguments: data (bytes): Bytes to pack padding (bytes): A single byte to use as padding if data is of uneven length endian (str): Endianness with which to pack the string ("little"/"big") Returns: A string representation of the packed data >>> js_escape(b'\xde\xad\xbe\xef') '%uadde%uefbe' >>> js_escape(b'\xde\xad\xbe\xef', endian='big') '%udead%ubeef' >>> js_escape(b'\xde\xad\xbe') '%uadde%u61be' >>> js_escape(b'aaaa') '%u6161%u6161' """ data = packing._need_bytes(data) padding = packing._need_bytes(padding) if len(padding) != 1: raise ValueError("Padding must be a single byte") if len(data) % 2: data += padding[0:1] data = bytearray(data) if context.endian == 'little': return ''.join('%u{a:02x}{b:02x}'.format(a=a, b=b) for b, a in iters.group(2, data)) else: return ''.join('%u{a:02x}{b:02x}'.format(a=a, b=b) for a, b in iters.group(2, data))