Exemple #1
0
    def unchunk(self, data, raw=False):
        if self.args.precision > self.args.blocksize:
            mask = (1 << (8 * self.args.blocksize)) - 1
            data = (chunk & mask for chunk in data)
        if not raw:
            return chunks.pack(data, self.args.blocksize, self.args.bigendian)

        def bytefilter(it):
            for item in it:
                if isinstance(item, (bytes, bytearray)):
                    yield item
                else:
                    yield bytes(item)

        return B''.join(bytefilter(data))
Exemple #2
0
 def decrypt(self, v: ByteString) -> ByteString:
     key = self._key
     v = self._unpack(v)
     n = len(v)
     r = 6 + 52 // n
     s = r * 0x9E3779B9 & 0xFFFFFFFF
     y = v[0]
     for _ in range(r):
         e = (s >> 2) & 3
         for p in range(n - 1, -1, -1):
             z = v[(p - 1) % n]
             k = (p & 3) ^ e
             x = ((z >> 5) ^ (y << 2)) + ((y >> 3) ^
                                          (z << 4)) ^ (s ^ y) + (key[k] ^ z)
             y = v[p] = v[p] - x & 0xFFFFFFFF
         s = s - 0x9E3779B9 & 0xFFFFFFFF
     return chunks.pack(v, 4)
Exemple #3
0
 def block_encrypt(self, block) -> BufferType:
     u = self._u
     w = self._w
     g = self._g
     r = self._r
     M = self._m
     S = self._S
     A, B, C, D = chunks.unpack(block, u)
     B = B + S[0] & M
     D = D + S[1] & M
     for i in range(1, r + 1):
         t = rotl(w, B * (2 * B + 1) & M, g)
         v = rotl(w, D * (2 * D + 1) & M, g)
         A = rotl(w, A ^ t, v) + S[2 * i + 0] & M
         C = rotl(w, C ^ v, t) + S[2 * i + 1] & M
         A, B, C, D = B, C, D, A
     A = A + S[2 * r + 2] & M
     C = C + S[2 * r + 3] & M
     return chunks.pack((A, B, C, D), u)
Exemple #4
0
 def block_decrypt(self, block) -> BufferType:
     u = self._u
     w = self._w
     g = self._g
     r = self._r
     M = self._m
     S = self._S
     A, B, C, D = chunks.unpack(block, u)
     C = C - S[2 * r + 3] & M
     A = A - S[2 * r + 2] & M
     for i in range(r, 0, -1):
         A, B, C, D = D, A, B, C
         t = rotl(w, B * (2 * B + 1) & M, g)
         v = rotl(w, D * (2 * D + 1) & M, g)
         C = rotr(w, C - S[2 * i + 1] & M, t) ^ v
         A = rotr(w, A - S[2 * i + 0] & M, v) ^ t
     D = D - S[1] & M
     B = B - S[0] & M
     return chunks.pack((A, B, C, D), u)
Exemple #5
0
 def encrypt(self, v: ByteString) -> ByteString:
     if not v:
         return v
     key = self._key
     v = list(self._unpack(v))
     n = len(v)
     s = 0
     r = 6 + 52 // n
     z = v[n - 1]
     for _ in range(r):
         s = s + 0x9E3779B9 & 0xFFFFFFFF
         e = (s >> 2) & 3
         for p in range(n):
             y = v[(p + 1) % n]
             k = (p & 3) ^ e
             x = ((z >> 5) ^ (y << 2)) + ((y >> 3) ^
                                          (z << 4)) ^ (s ^ y) + (key[k] ^ z)
             z = v[p] = v[p] + x & 0xFFFFFFFF
     return chunks.pack(v, 4)
Exemple #6
0
def ripemd128(message):

    R_ = [
        0x0,
        0x1,
        0x2,
        0x3,
        0x4,
        0x5,
        0x6,
        0x7,
        0x8,
        0x9,
        0xA,
        0xB,
        0xC,
        0xD,
        0xE,
        0xF,
        0x7,
        0x4,
        0xD,
        0x1,
        0xA,
        0x6,
        0xF,
        0x3,
        0xC,
        0x0,
        0x9,
        0x5,
        0x2,
        0xE,
        0xB,
        0x8,
        0x3,
        0xA,
        0xE,
        0x4,
        0x9,
        0xF,
        0x8,
        0x1,
        0x2,
        0x7,
        0x0,
        0x6,
        0xD,
        0xB,
        0x5,
        0xC,
        0x1,
        0x9,
        0xB,
        0xA,
        0x0,
        0x8,
        0xC,
        0x4,
        0xD,
        0x3,
        0x7,
        0xF,
        0xE,
        0x5,
        0x6,
        0x2,
    ]
    RP = [
        0x5,
        0xE,
        0x7,
        0x0,
        0x9,
        0x2,
        0xB,
        0x4,
        0xD,
        0x6,
        0xF,
        0x8,
        0x1,
        0xA,
        0x3,
        0xC,
        0x6,
        0xB,
        0x3,
        0x7,
        0x0,
        0xD,
        0x5,
        0xA,
        0xE,
        0xF,
        0x8,
        0xC,
        0x4,
        0x9,
        0x1,
        0x2,
        0xF,
        0x5,
        0x1,
        0x3,
        0x7,
        0xE,
        0x6,
        0x9,
        0xB,
        0x8,
        0xC,
        0x2,
        0xA,
        0x0,
        0x4,
        0xD,
        0x8,
        0x6,
        0x4,
        0x1,
        0x3,
        0xB,
        0xF,
        0x0,
        0x5,
        0xC,
        0x2,
        0xD,
        0x9,
        0x7,
        0xA,
        0xE,
    ]
    S_ = [
        0xB,
        0xE,
        0xF,
        0xC,
        0x5,
        0x8,
        0x7,
        0x9,
        0xB,
        0xD,
        0xE,
        0xF,
        0x6,
        0x7,
        0x9,
        0x8,
        0x7,
        0x6,
        0x8,
        0xD,
        0xB,
        0x9,
        0x7,
        0xF,
        0x7,
        0xC,
        0xF,
        0x9,
        0xB,
        0x7,
        0xD,
        0xC,
        0xB,
        0xD,
        0x6,
        0x7,
        0xE,
        0x9,
        0xD,
        0xF,
        0xE,
        0x8,
        0xD,
        0x6,
        0x5,
        0xC,
        0x7,
        0x5,
        0xB,
        0xC,
        0xE,
        0xF,
        0xE,
        0xF,
        0x9,
        0x8,
        0x9,
        0xE,
        0x5,
        0x6,
        0x8,
        0x6,
        0x5,
        0xC,
    ]
    SP = [
        0x8,
        0x9,
        0x9,
        0xB,
        0xD,
        0xF,
        0xF,
        0x5,
        0x7,
        0x7,
        0x8,
        0xB,
        0xE,
        0xE,
        0xC,
        0x6,
        0x9,
        0xD,
        0xF,
        0x7,
        0xC,
        0x8,
        0x9,
        0xB,
        0x7,
        0x7,
        0xC,
        0x7,
        0x6,
        0xF,
        0xD,
        0xB,
        0x9,
        0x7,
        0xF,
        0xB,
        0x8,
        0x6,
        0x6,
        0xE,
        0xC,
        0xD,
        0x5,
        0xE,
        0xD,
        0xD,
        0x7,
        0x5,
        0xF,
        0x5,
        0x8,
        0xB,
        0xE,
        0xE,
        0x6,
        0xE,
        0x6,
        0x9,
        0xC,
        0x9,
        0xC,
        0x5,
        0xF,
        0x8,
    ]

    def F0(x, y, z):
        return (x ^ y ^ z)

    def F1(x, y, z):
        return (x & y) | (z & ~x)

    def F2(x, y, z):
        return (x | (0xffffffff & ~y)) ^ z

    def F3(x, y, z):
        return (x & z) | (y & ~z)

    F = [F0, F1, F2, F3]

    K_ = [0x00000000, 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC]
    Kp = [0x50A28BE6, 0x5C4DD124, 0x6D703EF3, 0x00000000]

    h0 = 0x67452301
    h1 = 0xEFCDAB89
    h2 = 0x98BADCFE
    h3 = 0x10325476

    for block in _ripemd128_blocks(message):
        A_, B_, C_, D_ = h0, h1, h2, h3
        Ap, Bp, Cp, Dp = h0, h1, h2, h3
        for j in range(64):
            k = 63 - j
            tv = rol(
                A_ + F[j // 0x10](B_, C_, D_) + block[R_[j]] + K_[j // 0x10]
                & 0xFFFFFFFF, S_[j])
            A_, D_, C_, B_ = D_, C_, B_, tv
            tv = rol(
                Ap + F[k // 0x10](Bp, Cp, Dp) + block[RP[j]] + Kp[j // 0x10]
                & 0xFFFFFFFF, SP[j])
            Ap, Dp, Cp, Bp = Dp, Cp, Bp, tv
        tv = h1 + C_ + Dp & 0xFFFFFFFF
        h1 = h2 + D_ + Ap & 0xFFFFFFFF
        h2 = h3 + A_ + Bp & 0xFFFFFFFF
        h3 = h0 + B_ + Cp & 0xFFFFFFFF
        h0 = tv

    return chunks.pack((h0, h1, h2, h3), 4)
Exemple #7
0
    def keystream(self) -> Iterable[int]:
        key = self.args.key

        A: int = 0
        B: int = 0
        C: int = 0
        S: List[int] = [0x9E3779B9] * 8
        T: List[int] = []
        K = list(
            chunks.unpack(key + bytearray(0x400 - len(key)),
                          4,
                          bigendian=False))
        U = 0xFFFFFFFF

        def _mix_state():
            a, b, c, d, e, f, g, h = S
            a ^= (b << 0x0B) & U
            d = d + a & U
            b = b + c & U  # noqa
            b ^= (c >> 0x02) & U
            e = e + b & U
            c = c + d & U  # noqa
            c ^= (d << 0x08) & U
            f = f + c & U
            d = d + e & U  # noqa
            d ^= (e >> 0x10) & U
            g = g + d & U
            e = e + f & U  # noqa
            e ^= (f << 0x0A) & U
            h = h + e & U
            f = f + g & U  # noqa
            f ^= (g >> 0x04) & U
            a = a + f & U
            g = g + h & U  # noqa
            g ^= (h << 0x08) & U
            b = b + g & U
            h = h + a & U  # noqa
            h ^= (a >> 0x09) & U
            c = c + h & U
            a = a + b & U  # noqa
            S[:] = a, b, c, d, e, f, g, h
            return S

        def _initialize_with(R: List[int]):
            for i in range(0, 0x100, 8):
                S[:] = (x + R[j] & U for j, x in enumerate(S, i))
                T[i:i + 8] = _mix_state()

        for _ in range(4):
            _mix_state()

        _initialize_with(K)
        _initialize_with(T)

        operations = [
            (__lshift__, 0x0D),
            (__rshift__, 0x06),
            (__lshift__, 0x02),
            (__rshift__, 0x10),
        ]

        while True:
            C = (C + 1) & U
            B = (B + C) & U
            for i in range(0x100):
                X = T[i]
                shift, k = operations[i % 4]
                A = (A ^ shift(A, k)) & U
                A = (A + T[i ^ 0x80]) & U
                Y = T[+i] = T[X // 4 & 0xFF] + A + B & U
                B = K[~i] = X + T[Y // 1024 & 0xFF] & U
            yield from chunks.pack(K, 4, True)
Exemple #8
0
    def process(self, data):
        header = DotNetHeader(data, parse_resources=False)
        decompressor = lzma()

        class IntegerAssignment:
            def __init__(self, match):
                self.offset = match.start()
                self.value, = struct.unpack('<I', match[1])

        def get_size(match):
            ins = match[1]
            fmt = '<B' if ins[0] == 0x1F else '<I'
            result, = struct.unpack(fmt, ins[-struct.calcsize(fmt):])
            return result

        potential_seeds = [
            IntegerAssignment(m)
            for m in re.finditer(br'\x20(....)', data, re.DOTALL)
        ]

        for entry in header.meta.RVAs:
            offset = header.pe.get_offset_from_rva(entry.RVA)
            index = struct.pack('<I', entry.Field.Index)
            strings_found = 0
            for match in re.finditer(self._PATTERN_ARRAY_INIT %
                                     re.escape(index[:3]),
                                     data,
                                     flags=re.DOTALL):
                ms = match.start()

                def sortkey(t):
                    weight = abs(t.offset - ms)
                    if t.offset < ms:
                        # this weights assignments after the array initialization down, but still
                        # prefers them over assignments that are further away than 2kb
                        weight += 2000
                    return weight

                size = get_size(match)

                if size % 0x10 or size > 10000:
                    continue

                self.log_debug(
                    F'found RVA {entry.Field.Index} initialized with length {size}.'
                )
                potential_seeds.sort(key=sortkey)

                for seed in potential_seeds[1:400]:
                    # the first potential_seed will always be the assignment of the size variable
                    ciphertext = data[offset:offset + size * 4]
                    key = self._xs64star(seed.value)
                    key = chunks.pack(key, 4) + ciphertext[:-0x40]
                    decrypted = strxor(key, ciphertext)
                    try:
                        decompressed = decompressor(decrypted)
                    except Exception as e:
                        self.log_debug(
                            F'decompression failed for seed {seed.value:08X} at offset {seed.offset:08X}: {e}'
                        )
                        continue
                    else:
                        self.log_info(
                            F'decompression worked for seed {seed.value:08X} at offset {seed.offset:08X}.'
                        )
                    if len(decompressed) < 0x100:
                        continue
                    for string in self._extract_strings(decompressed):
                        strings_found += 1
                        yield string
                    if strings_found > 10:
                        break