Source code for malduck.string.ops
# Copyright (C) 2018 Jurriaan Bremer.
# This file is part of Roach - https://github.com/jbremer/roach.
# See the file 'docs/LICENSE.txt' for copying permission.
from base64 import b64decode, b64encode
import binascii
from ..py2compat import indexbytes, int2byte
__all__ = [
"asciiz",
"chunks_iter",
"chunks",
"utf16z",
"enhex",
"unhex",
"uleb128",
"Base64",
"Padding",
"Unpadding",
"base64",
"pad",
"pkcs7",
"unpad",
"unpkcs7",
]
[docs]def asciiz(s):
"""
Treats s as null-terminated ASCII string
:param s: Buffer containing null-terminated ASCII string
:type s: bytes
"""
return s.split(b"\x00")[0]
[docs]def chunks_iter(s, n):
"""Yield successive n-sized chunks from s."""
for i in range(0, len(s), n):
yield s[i : i + n]
[docs]def chunks(s, n):
"""Return list of successive n-sized chunks from s."""
return list(chunks_iter(s, n))
[docs]def utf16z(s):
"""
Treats s as null-terminated UTF-16 ASCII string
:param s: Buffer containing null-terminated UTF-16 string
:type s: bytes
:return: ASCII string without '\x00' terminator
:rtype: bytes
"""
chunked = chunks(s, 2)
if b"\x00\x00" in chunked:
return (
s[: chunked.index(b"\x00\x00") * 2]
.decode("utf-16")
.rstrip("\x00")
.encode("ascii")
)
return s
[docs]def enhex(s):
"""
.. versionchanged:: 2.0.0
Renamed from :py:meth:`malduck.hex`
"""
return binascii.hexlify(s)
[docs]def unhex(s):
return binascii.unhexlify(s)
[docs]def uleb128(s):
"""Unsigned Little-Endian Base 128"""
ret = 0
for idx in range(len(s)):
ret += (indexbytes(s, idx) & 0x7F) << (idx * 7)
if indexbytes(s, idx) < 0x80:
break
else:
return None
return idx + 1, ret
class Base64(object):
"""Base64 encoder/decoder"""
def encode(self, s):
return b64encode(s)
def decode(self, s):
return b64decode(s)
__call__ = decode
class Padding(object):
"""
Padding PKCS7/NULL
"""
def __init__(self, style):
self.style = style
@staticmethod
def null(s, block_size):
return Padding("null").pad(s, block_size)
def pad(self, s, block_size):
length = block_size - len(s) % block_size
if length == block_size:
padding = b""
elif self.style == "pkcs7":
padding = int2byte(length) * length
elif self.style == "null":
padding = b"\x00" * length
else:
raise ValueError("Unknown padding {}".format(self.style))
return s + padding
__call__ = pkcs7 = pad
class Unpadding(object):
"""
Unpadding PKCS7/NULL
"""
def __init__(self, style):
self.style = style
def unpad(self, s):
count = indexbytes(s, -1) if s else 0
if self.style == "pkcs7" and s[-count:] == int2byte(indexbytes(s, -1)) * count:
return s[:-count]
return s
__call__ = pkcs7 = unpad
base64 = Base64()
pad = Padding("pkcs7")
pkcs7 = Padding("pkcs7")
unpad = Unpadding("pkcs7")
unpkcs7 = Unpadding("pkcs7")