コード例 #1
0
ファイル: test_multibin.py プロジェクト: larsborn/refinery
 def test_range_modifier(self):
     m = multibin('range:0x31:0x39+1')
     self.assertEqual(m, B'123456789')
コード例 #2
0
ファイル: meta.py プロジェクト: binref/refinery
    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()
コード例 #3
0
ファイル: test_multibin.py プロジェクト: larsborn/refinery
 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))
コード例 #4
0
ファイル: test_multibin.py プロジェクト: larsborn/refinery
 def test_unit_loader(self):
     m = multibin('hex[-R]:x::4')
     b = bytearray.fromhex('BAADF00DCAB00F')
     a = m(b)
     self.assertEqual(a, B'BAADF00D')
コード例 #5
0
ファイル: test_multibin.py プロジェクト: larsborn/refinery
 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))
コード例 #6
0
ファイル: test_multibin.py プロジェクト: larsborn/refinery
 def test_invalid_multibin_modifier(self):
     self.assertEqual(multibin('foobar:s:content'), B'foobar:s:content')
コード例 #7
0
ファイル: test_multibin.py プロジェクト: binref/refinery
 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')
コード例 #8
0
ファイル: test_multibin.py プロジェクト: binref/refinery
 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')
コード例 #9
0
ファイル: test_multibin.py プロジェクト: binref/refinery
 def test_reversed_multibin(self):
     m = multibin('636D566D6157356C636E6B3D:H:b64', reverse=True)
     self.assertEqual(m, B'refinery')
コード例 #10
0
 def test_itob_byte_width(self):
     self.assertEqual(argformats.multibin('itob[1]:eval:(0x00,0x12,0x3412)'), b'\0\x12\x12')
コード例 #11
0
 def test_empty_value_passed_to_itob(self):
     self.assertEqual(argformats.multibin('itob:take[:0]:foo'), b'')
コード例 #12
0
 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')
     )
コード例 #13
0
 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))