def test_range_modifier(self): m = multibin('range:0x31:0x39+1') self.assertEqual(m, B'123456789')
def format(self, spec: str, codec: str, args: Union[list, tuple], symb: dict, binary: bool, fixup: bool = True, used: Optional[set] = None, escaped: bool = False) -> Union[str, ByteString]: """ Formats a string using Python-like string fomatting syntax. The formatter for `binary` mode is different; each formatting is documented in one of the following two proxy methods: - `refinery.lib.meta.LazyMetaOracle.format_str` - `refinery.lib.meta.LazyMetaOracle.format_bin` """ from refinery.lib.argformats import multibin, ParserError, PythonExpression # prevents circular import symb = symb or {} if used is None: class dummy: def add(self, _): pass used = dummy() if args is None: args = () elif not isinstance(args, (list, tuple)): args = list(args) if fixup: for (store, it) in ( (args, enumerate(args)), (self, self.items()), (symb, symb.items()), ): for key, value in it: with contextlib.suppress(TypeError): if isinstance(value, CustomStringRepresentation): continue store[key] = ByteStringWrapper(value, codec) formatter = string.Formatter() autoindex = 0 if binary: stream = MemoryFile() def putstr(s: str): stream.write(s.encode(codec)) else: stream = StringIO() putstr = stream.write with stream: for prefix, field, modifier, conversion in formatter.parse(spec): output = value = None if prefix: if binary: prefix = prefix.encode(codec) elif escaped: prefix = prefix.encode('raw-unicode-escape').decode( 'unicode-escape') stream.write(prefix) if field is None: continue if not field: if not args: raise LookupError( 'no positional arguments given to formatter') value = args[autoindex] used.add(autoindex) if autoindex < len(args) - 1: autoindex += 1 if binary and conversion: conversion = conversion.lower() if conversion == 'h': value = bytes.fromhex(field) elif conversion == 'q': value = unquote_to_bytes(field) elif conversion == 's': value = field.encode(codec) elif conversion == 'u': value = field.encode('utf-16le') elif conversion == 'a': value = field.encode('latin1') elif conversion == 'e': value = field.encode(codec).decode( 'unicode-escape').encode('latin1') elif field in symb: value = symb[field] used.add(field) if value is None: with contextlib.suppress(ValueError, IndexError): index = int(field, 0) value = args[index] used.add(index) if value is None: with contextlib.suppress(KeyError): value = self[field] used.add(field) if value is None: try: expression = PythonExpression(field, *self, *symb) value = expression(self, **symb) except ParserError: if not self.ghost: raise KeyError(field) putstr(F'{{{field}') if conversion: putstr(F'!{conversion}') if modifier: putstr(F':{modifier}') putstr('}') continue if binary: modifier = modifier.strip() if modifier: expression = self.format(modifier, codec, args, symb, True, False, used) output = multibin(expression.decode(codec), reverse=True, seed=value) elif isbuffer(value): output = value elif not isinstance(value, int): with contextlib.suppress(TypeError): output = bytes(value) if output is None: converter = { 'a': ascii, 's': str, 'r': repr, 'H': lambda b: b.hex().upper(), 'h': lambda b: b.hex(), 'u': lambda b: b.decode('utf-16le'), 'e': lambda b: repr(bytes(b)).lstrip('bBrR')[1:-1], 'q': lambda b: quote_from_bytes(bytes(b)) }.get(conversion) if converter: output = converter(value) elif modifier: output = value elif isinstance(value, CustomStringRepresentation): output = str(value) elif isbuffer(value): output = value.decode('utf8', errors='replace') else: output = value output = output.__format__(modifier) if binary: output = output.encode(codec) stream.write(output) return stream.getvalue()
def test_multibin_nested_args(self): buffer = B'Too much Technology in too little Time' m = multibin(F'xor[ucrypt[8,H:4242]:swordfish]:H:{buffer.hex()}') ucrypt = self.ldu('ucrypt', size=8, salt=bytes.fromhex('4242')) self.assertEqual(m, self.ldu('xor', ucrypt(B'swordfish'))(buffer))
def test_unit_loader(self): m = multibin('hex[-R]:x::4') b = bytearray.fromhex('BAADF00DCAB00F') a = m(b) self.assertEqual(a, B'BAADF00D')
def test_multibin_simple(self): m = multibin('xor[0x50]:x:-16:') b = bytearray([4] * 12 + [5] * 16) a = m(b) self.assertEqual(a, 16 * B'\x55') self.assertEqual(b, bytearray([4] * 12))
def test_invalid_multibin_modifier(self): self.assertEqual(multibin('foobar:s:content'), B'foobar:s:content')
def test_readme_01(self): m = multibin('repl[q:1%2c2%2c3,2]:1,2,3,4,5') self.assertEqual(m, B'2,4,5')
def test_seeded_multibin(self): for spec, r in (('b64:h', False), ('b64:h:', False), ('h:b64', True), (':h:b64', True)): m = multibin(spec, reverse=r, seed=b'636D566D6157356C636E6B3D') self.assertEqual(m, B'refinery')
def test_reversed_multibin(self): m = multibin('636D566D6157356C636E6B3D:H:b64', reverse=True) self.assertEqual(m, B'refinery')
def test_itob_byte_width(self): self.assertEqual(argformats.multibin('itob[1]:eval:(0x00,0x12,0x3412)'), b'\0\x12\x12')
def test_empty_value_passed_to_itob(self): self.assertEqual(argformats.multibin('itob:take[:0]:foo'), b'')
def test_accu(self): self.assertEqual( argformats.multibin('itob[1]:take[:16]:accu:@msvc'), bytes.fromhex('26 27 F6 85 97 15 AD 1D D2 94 DD C4 76 19 39 31') )
def test_multibin_nested_args(self): buffer = B'Too much Technology in too little Time' m = multibin(F'xor[ucrypt[8,H:4242]:swordfish]:H:{buffer.hex()}') ucrypt = refinery.ucrypt(size=8, salt=bytes.fromhex('4242')) self.assertEqual(m, refinery.xor(arg=[ucrypt(B'swordfish')])(buffer))