Module refinery.lib.unquarantine
Implements extraction logic for anti-virus quarantine containers. Each handler function accepts a
memoryview of the quarantine file and returns a QuarantineResult on
success or None on failure. The public entry point is unquarantine().
This library is largely untested. Acquiring test samples is difficult. If you have atest samples, please let me know.
Expand source code Browse git
"""
Implements extraction logic for anti-virus quarantine containers. Each handler function accepts a
memoryview of the quarantine file and returns a `refinery.lib.unquarantine.QuarantineResult` on
success or `None` on failure. The public entry point is `refinery.lib.unquarantine.unquarantine`.
This library is largely untested. Acquiring test samples is difficult. If you have atest samples,
please let me know.
"""
from __future__ import annotations
import enum
import struct
import zlib
from typing import NamedTuple
class QuarantineResult(NamedTuple):
data: bytes | bytearray
vendor: str
filename: str | None = None
threat: str | None = None
def _rc4(key: bytes | bytearray, data: bytes | bytearray | memoryview) -> bytearray:
from Cryptodome.Cipher import ARC4
return bytearray(ARC4.new(key).encrypt(bytes(data)))
def _blowfish_ecb(key: bytes | bytearray, data: bytes | bytearray | memoryview) -> bytearray:
from Cryptodome.Cipher import Blowfish
cipher = Blowfish.new(key, Blowfish.MODE_ECB)
raw = bytes(data)
pad = 8 - len(raw) % 8
if pad < 8:
raw += b'\x00' * pad
return bytearray(cipher.decrypt(raw))[:len(data)]
def _blowfish_ecb_swap(
key: bytes | bytearray,
data: bytes | bytearray | memoryview,
) -> bytearray:
from Cryptodome.Cipher import Blowfish
cipher = Blowfish.new(key, Blowfish.MODE_ECB)
raw = bytes(data)
pad = 8 - len(raw) % 8
if pad < 8:
raw += b'\x00' * pad
out = bytearray()
for k in range(0, len(raw), 8):
block = raw[k:k + 8]
a = struct.pack('>I', struct.unpack('<I', block[0:4])[0])
b = struct.pack('>I', struct.unpack('<I', block[4:8])[0])
dec = cipher.decrypt(a + b)
a = struct.pack('>I', struct.unpack('<I', dec[0:4])[0])
b = struct.pack('>I', struct.unpack('<I', dec[4:8])[0])
out.extend(a + b)
return out[:len(data)]
def _md5(data: bytes) -> bytes:
from Cryptodome.Hash import MD5
return MD5.new(data).digest()
def _u16(data: bytes | bytearray | memoryview, offset: int = 0) -> int:
return struct.unpack_from('<H', data, offset)[0]
def _u32(data: bytes | bytearray | memoryview, offset: int = 0) -> int:
return struct.unpack_from('<I', data, offset)[0]
def _u64(data: bytes | bytearray | memoryview, offset: int = 0) -> int:
return struct.unpack_from('<Q', data, offset)[0]
def _xor_byte(data: bytes | bytearray | memoryview, key: int) -> bytearray:
out = bytearray(data)
for i in range(len(out)):
out[i] ^= key
return out
def _xor_cyclic(
data: bytes | bytearray | memoryview,
key: bytes | bytearray,
) -> bytearray:
klen = len(key)
out = bytearray(data)
for i in range(len(out)):
out[i] ^= key[i % klen]
return out
_KEY_V3B = bytes(b ^ 0xFF for b in b'v3backup!@#$%^&)')
_KEY_AVAST = bytes([
0x33, 0xB6, 0x59, 0x83, 0x8B, 0x43, 0x75, 0xFB, 0x35, 0xB6, 0x8A, 0x37,
0xAE, 0x29, 0x16, 0x47, 0xA2, 0x51, 0x41, 0x4F, 0x69, 0x9A, 0x07, 0xF5,
0xF1, 0x69, 0x80, 0x89, 0x60, 0x15, 0x8E, 0xF6, 0xB2, 0x3B, 0x89, 0xC4,
0x9F, 0xFF, 0x65, 0x2E, 0x36, 0xD3, 0xF2, 0x10, 0xEA, 0x76, 0x88, 0xAD,
0x19, 0x39, 0x44, 0xEF, 0x7E, 0xBC, 0xAF, 0xA0, 0x26, 0x7D, 0x83, 0xC9,
0x13, 0xC7, 0xBD, 0xE1, 0x16, 0xEB, 0x27, 0x69, 0x2C, 0x17, 0xE2, 0xF9,
0xF8, 0x8A, 0x7F, 0x6E, 0x6F, 0xEB, 0x16, 0x16, 0x60, 0x48, 0x86, 0x12,
0xC5, 0x9A, 0x91, 0x6B, 0xB3, 0xA2, 0x71, 0x38, 0xC6, 0x2F, 0x4E, 0x05,
0x8D, 0x7E, 0xE8, 0x98, 0x30, 0xFF, 0x6F, 0xB2, 0xBD, 0x03, 0x35, 0x71,
0xD3, 0xF6, 0x08, 0x0F, 0x0F, 0x08, 0xE3, 0x73, 0xA6, 0xA0, 0x2E, 0x02,
0x76, 0x7F, 0x97, 0x9F, 0x8E, 0x5D, 0x80, 0xDE, 0x75, 0xDB, 0x41, 0x31,
0x62, 0xCC, 0x68, 0x73, 0x79, 0x33, 0x3F, 0xE8, 0xDC, 0xCD, 0xF5, 0x9A,
0x9E, 0x1F, 0x21, 0xD7, 0x97, 0xDF, 0x66, 0xC8, 0x50, 0x0F, 0xBD, 0x2E,
0x35, 0x11, 0x1D, 0x77, 0xE1, 0x62, 0xA1, 0xCA, 0x4C, 0xC7, 0x4C, 0xE3,
0xB5, 0x5C, 0x86, 0xD5, 0xE4, 0xCE, 0xF5, 0xD3, 0xCF, 0xA5, 0xE6, 0x54,
0xA7, 0x2E, 0x7B, 0xA8, 0xBA, 0xA5, 0x8B, 0x02, 0x15, 0x4E, 0xEE, 0xD6,
0xB1, 0xE4, 0xEB, 0x46, 0x9B, 0x8B, 0xB5, 0x26, 0xCA, 0x88, 0xAF, 0xE6,
0xF8, 0x56, 0xFA, 0x6F, 0x39, 0x48, 0x6B, 0xFA, 0xF0, 0x7A, 0x4F, 0xC4,
0xE3, 0xA7, 0x2C, 0x62, 0x44, 0x84, 0x39, 0xE3, 0xDD, 0xED, 0xA4, 0xF6,
0xFD, 0x4E, 0xB8, 0x92, 0x0C, 0x1D, 0x3A, 0x78, 0x7E, 0xDD, 0x03, 0x3E,
0xD1, 0x7B, 0xE6, 0x2C, 0xBE, 0xD3, 0x87, 0x75, 0xD5, 0xE1, 0x2F, 0x07,
0x19, 0x37, 0x01, 0x40, 0x8D, 0x7E, 0xE8, 0x98, 0x30, 0xFF, 0x6F, 0xB2,
0xBD, 0x03, 0x35, 0x71, 0xD3, 0xF6, 0x08, 0x0F, 0x6F, 0x43, 0x73, 0x1E,
0x13, 0x7D, 0x30, 0x3D, 0xFA, 0x30, 0x5B, 0x81, 0x68, 0x7C, 0xF9, 0xEA,
0x52, 0xA9, 0xE3, 0xF4, 0x28, 0x8C, 0x01, 0x38, 0xAF, 0xE9, 0xD0, 0xA8,
0x2C, 0xD4, 0x62, 0xE8, 0x41, 0xA5, 0xB1, 0x71, 0xC1, 0x2E, 0x2B, 0x79,
0xE3, 0xFF, 0xA8, 0x24, 0x12, 0xAF, 0x89, 0xA7, 0x9A, 0x6D, 0x73, 0xE6,
0xCD, 0xE8, 0x11, 0x75, 0xFF, 0xE6, 0x70, 0x8A, 0x8A, 0xE5, 0x4F, 0x08,
0x8D, 0x7E, 0xE8, 0x98, 0x30, 0xFF, 0x6F, 0xB2, 0xBD, 0x03, 0x35, 0x71,
0xD3, 0xF6, 0x08, 0x0F, 0x32, 0x91, 0x88, 0xC4, 0x01, 0x19, 0x08, 0x2F,
0x48, 0x84, 0xD2, 0x30, 0x5F, 0x56, 0xB7, 0x15, 0xAF, 0x90, 0x52, 0x1A,
0x1B, 0x16, 0xCD, 0x84, 0xEA, 0x6E, 0xE6, 0x9A, 0x89, 0xC3, 0x48, 0xF0,
0x9C, 0xBD, 0xC3, 0x95, 0x18, 0xF9, 0x30, 0xC0, 0xD2, 0x50, 0x21, 0x66,
0x41, 0xA1, 0x82, 0xB6, 0xA5, 0x57, 0x64, 0x6A, 0x96, 0x96, 0x8C, 0x1D,
0x94, 0x74, 0xD6, 0x2F, 0x77, 0x12, 0x4B, 0x3F, 0xF6, 0x5C, 0x33, 0x8C,
0xA1, 0x21, 0x7F, 0x3C, 0x5B, 0x9D, 0xCB, 0x2C, 0x1F, 0x6E, 0xA0, 0xAA,
0x8F, 0xEA, 0x09, 0x90, 0x4B, 0x47, 0xD0, 0x27, 0xA7, 0x9A, 0x89, 0x78,
0x9E, 0x20, 0xF2, 0x8E, 0x81, 0x12, 0xDD, 0x09, 0xDF, 0x0D, 0x7F, 0x4B,
0x76, 0xB5, 0x89, 0xA7, 0x69, 0x7F, 0x42, 0x15, 0x22, 0x7F, 0xE9, 0x59,
0xA6, 0xFD, 0x59, 0x2A, 0x8E, 0x58, 0x25, 0xCC, 0xFC, 0x63, 0x88, 0xC5,
0x64, 0x22, 0x71, 0x48, 0x2E, 0xC9, 0xC8, 0xE3, 0xAE, 0xB4, 0x94, 0xBD,
0x73, 0x7A, 0x11, 0x04, 0x37, 0x0C, 0xF0, 0x04, 0x1D, 0x57, 0x62, 0x6F,
0x65, 0xFE, 0x57, 0x97, 0xBA, 0x44, 0x81, 0xA7, 0x9D, 0xB4, 0xFC, 0x16,
0x3E, 0xB5, 0x05, 0xED, 0xD1, 0x67, 0xD5, 0x2A, 0xE7, 0xCF, 0xD5, 0xD5,
0xD4, 0xC8, 0x4A, 0x1F, 0x85, 0x39, 0x79, 0xDF, 0xB7, 0x1E, 0x79, 0x75,
0xC3, 0xB3, 0xB4, 0xCA, 0xA1, 0x3D, 0x38, 0x54, 0xC6, 0x42, 0x17, 0x3B,
0x57, 0x02, 0xB9, 0xDC, 0xDE, 0xC8, 0x1F, 0x88, 0x0A, 0x9B, 0xB7, 0x4E,
0x95, 0x25, 0xCE, 0xC8, 0x3F, 0x02, 0x74, 0xFD, 0xB8, 0xA2, 0x5C, 0x12,
0x1D, 0xD6, 0x25, 0x37, 0xE3, 0xD3, 0x6C, 0x2A, 0x9D, 0x8F, 0x93, 0x26,
0xE3, 0x3F, 0xC1, 0xD6, 0xBE, 0x14, 0x8E, 0xEF, 0x08, 0xBC, 0x4D, 0xB4,
0xDE, 0xE9, 0x05, 0x14, 0x29, 0xA0, 0x3A, 0x57, 0xEB, 0x52, 0x47, 0xD7,
0xDE, 0x1D, 0x42, 0x97, 0x51, 0xD3, 0x85, 0x0D, 0xA7, 0xF0, 0xF7, 0xD3,
0x30, 0xFC, 0x78, 0xC3, 0x77, 0x73, 0x8D, 0x8E, 0xF4, 0x18, 0x2D, 0x33,
0xC6, 0xE9, 0x9F, 0xE3, 0x1E, 0x81, 0x8A, 0x99, 0xDB, 0x26, 0x36, 0x8D,
0xC1, 0x9D, 0xC0, 0x03, 0xF2, 0xB7, 0xBC, 0xA3, 0xBD, 0x22, 0xA8, 0xAF,
0x5D, 0x37, 0x1A, 0x3E, 0x1D, 0x9C, 0x48, 0xD6, 0xA8, 0x0D, 0x21, 0xA6,
0x7A, 0xC0, 0x11, 0x37, 0xB3, 0x97, 0x5D, 0x50, 0x5A, 0xE8, 0xDC, 0xC6,
0x7F, 0xF8, 0x16, 0x35, 0xED, 0x28, 0xEF, 0x51, 0xEE, 0x05, 0x43, 0x4F,
0x62, 0x15, 0xBE, 0x8B, 0x88, 0x0F, 0x6C, 0xB0, 0x57, 0x69, 0x57, 0xB1,
0xFF, 0x76, 0x44, 0x64, 0x6C, 0xA3, 0x12, 0x9C, 0x54, 0x5C, 0x7B, 0xA2,
0xC3, 0xAD, 0x26, 0x60, 0xDE, 0xF0, 0x5D, 0x23, 0xA3, 0x28, 0xF5, 0xAB,
0x88, 0x8B, 0x61, 0x85, 0x02, 0xC8, 0xB3, 0x1D, 0x41, 0xD2, 0x30, 0x0B,
0x22, 0x2C, 0xEA, 0xD3, 0xC9, 0xEB, 0x3F, 0x23, 0x80, 0xDA, 0xC3, 0x84,
0x0F, 0x6C, 0xD4, 0xCC, 0x1E, 0x5F, 0x6D, 0x22, 0xAC, 0x74, 0x1D, 0xD2,
0x09, 0x3A, 0x1B, 0x28, 0x08, 0xB6, 0xED, 0x92, 0xE6, 0xA5, 0xAD, 0x9B,
0x84, 0x09, 0x40, 0xA2, 0x91, 0x6C, 0x1A, 0x90, 0x72, 0x8E, 0x54, 0x63,
0x16, 0xA6, 0xDD, 0xFC, 0xF3, 0x23, 0x3E, 0x11, 0xF0, 0x0A, 0x32, 0x2C,
0x7B, 0x81, 0x60, 0xFF, 0x61, 0xF7, 0x4A, 0x7A, 0x07, 0x10, 0x7B, 0xEB,
0x68, 0x90, 0x56, 0xD9, 0x6A, 0x3D, 0xDB, 0x22, 0x31, 0x65, 0xA2, 0x2D,
0xA4, 0xB4, 0x82, 0xC3, 0xEA, 0x7C, 0xF8, 0x24, 0x88, 0x80, 0x4A, 0x2F,
0xA9, 0x56, 0x55, 0xBD, 0x2E, 0x88, 0xF7, 0x26, 0x36, 0x1D, 0x18, 0x65,
0xF9, 0xB7, 0xB3, 0x63, 0xB2, 0xE6, 0x0F, 0x76, 0x5A, 0xF4, 0x3A, 0x0A,
0xB7, 0x6C, 0x11, 0x1F, 0x00, 0xCC, 0x31, 0x16, 0x5C, 0x6F, 0x51, 0x2C,
0xC4, 0xD9, 0xEE, 0xF6, 0xC4, 0xF9, 0x2D, 0x81, 0x6E, 0xF1, 0xCD, 0x13,
0x44, 0x77, 0x43, 0x67, 0xBD, 0xB6, 0x14, 0x91, 0xD9, 0x32, 0xB2, 0xFF,
0x96, 0x46, 0x26, 0xC4, 0x62, 0x1E, 0x6C, 0xB4, 0x3A, 0xC5, 0xBC, 0xB8,
0xEA, 0x40, 0x7B, 0x72, 0x7F, 0xF8, 0x82, 0xDC, 0x67, 0x47, 0xF2, 0x38,
0x66, 0xC6, 0x73, 0xD5, 0xA9, 0x8F, 0x48, 0xE5, 0x10, 0x54, 0x7B, 0x43,
0xFD, 0xEE, 0x9B, 0x1C, 0x12, 0x55, 0x15, 0x20, 0xF8, 0x23, 0x0F, 0x95,
0x85, 0xCB, 0x5F, 0xF5, 0x1B, 0x57, 0x4F, 0x25, 0x0B, 0xCA, 0xA1, 0x6A,
0x6D, 0xF2, 0x69, 0xD8, 0x8E, 0x40, 0xEC, 0x64, 0x60, 0x93, 0x43, 0x3A,
0x01, 0x77, 0xBC, 0x4B, 0x72, 0x73, 0x23, 0xF5, 0xD1, 0x0C, 0x70, 0x1B,
0x71, 0xE3, 0x95, 0xF9, 0x51, 0x7D, 0xAB, 0x40, 0x46, 0xB3, 0xEC, 0x38,
0x2A, 0xFB, 0x9C, 0xB9, 0xA2, 0x69, 0xE4, 0x22, 0xBD, 0xB1, 0x6B, 0x08,
0xA9, 0xE0, 0xE7, 0x66, 0x48, 0xF1, 0xB0, 0x2D, 0x6B, 0x53, 0x8B, 0x62,
0x54, 0xD4, 0xE8, 0x48, 0xDA, 0xFB, 0xE0, 0x8C, 0x0B, 0x8A, 0x9D, 0xA4,
0x46, 0x88, 0x5B, 0x47, 0xE5, 0x2A, 0xF6, 0x84, 0xB3, 0xAE, 0x31, 0xF6,
0xC5, 0x3F, 0x11, 0x59, 0x40, 0x7C, 0x66, 0x74, 0x8D, 0xA3, 0x1A, 0x13,
0x7E, 0xD6, 0x90, 0xCD, 0xC8, 0x97, 0xAF, 0x33, 0xBA, 0xAD, 0xF6, 0xDE,
0x64, 0x41, 0xD3, 0xAE, 0x08, 0x00, 0xF6, 0x2F, 0x73, 0xD3, 0x21, 0x64,
0x4E, 0xC5, 0x27, 0xFA, 0xB6, 0x62, 0x02, 0xB9, 0x37, 0xD2, 0x22, 0x9D,
0xE6, 0x9F, 0x08, 0x47, 0xFB, 0x05, 0x1E, 0xB8, 0x2C, 0xE4, 0xC5, 0x92,
0x91, 0xAA, 0x50, 0xA3, 0xE4, 0x78, 0x80, 0xC5, 0xB0, 0x14, 0x4F, 0x90,
0x11, 0x4D, 0x80, 0xEB, 0x20, 0x25, 0x3C, 0x3F, 0x03, 0xF6, 0xFC, 0xFE,
0xAE, 0xCD, 0x0F, 0x48, 0xF5, 0x90, 0xE2, 0x9E, 0xC1, 0x6C, 0xA3, 0x33,
0xEB, 0xD9, 0xA4, 0xE9, 0x33, 0x0D, 0xE2, 0x5D, 0x4A, 0x48, 0xC9, 0xCE,
0xF4, 0xDF, 0xE9, 0xD2, 0x8D, 0xDB, 0x3D, 0x2E, 0xE9, 0x0C, 0xBE, 0x8D,
0x36, 0x4B, 0xD3, 0xA9, 0xA7, 0xC9, 0xE5, 0xB6, 0xFB, 0x83, 0x37, 0xD5,
0x65, 0x31, 0x61, 0x7F, 0x30, 0xDC, 0x4B, 0xB6, 0x30, 0xCD, 0x44, 0xE0,
0x9B, 0x07, 0x4E, 0x00, 0x89, 0x80, 0xAC, 0xC9, 0xFB, 0x86, 0x4E, 0x78,
0xA2, 0x48, 0x17, 0x34, 0x67, 0x94, 0x11, 0x60, 0x67, 0xFC, 0x61, 0x74,
0xC1, 0x6B, 0x40, 0x47, 0xA1, 0x22, 0x75, 0xCA, 0x56, 0x99, 0x0B, 0xBB,
0x33, 0x07, 0xA2, 0x88, 0x78, 0xAE, 0xF6, 0x1B, 0x8D, 0x7E, 0xE8, 0x98,
0x30, 0xFF, 0x6F, 0xB2, 0xBD, 0x03, 0x35, 0x71, 0xD3, 0xF6, 0x08, 0x0F,
0x59, 0x40, 0xBA, 0x35, 0x0A, 0x34, 0x21, 0x3C, 0x8D, 0xDA, 0x9B, 0x9D,
0x16, 0xCB, 0x22, 0x63, 0x27, 0xA4, 0x3A, 0xD1, 0x0E, 0xCB, 0x79, 0x87,
0x34, 0x89, 0xE9, 0x8F, 0x9B, 0x0E, 0xC8, 0x05, 0x8D, 0x7E, 0xE8, 0x98,
0x30, 0xFF, 0x6F, 0xB2, 0xBD, 0x03, 0x35, 0x71, 0xD3, 0xF6, 0x08, 0x0F,
0xF4, 0x03, 0xFC, 0xBE, 0x12, 0xEB, 0xDA, 0x57, 0x28, 0x28, 0x26, 0x43,
0xCF, 0xC4, 0x71, 0xBF, 0x60, 0x51, 0x33, 0xBF, 0x3D, 0xC1, 0xB6, 0xBB,
0x18, 0x39, 0xCC, 0xE0, 0x8B, 0x66, 0x33, 0xC2, 0x82, 0x79, 0x3E, 0xFC,
0x73, 0x7C, 0xD2, 0xD5, 0xF9, 0x7D, 0x83, 0xA6, 0x2C, 0x1B, 0x0B, 0x76,
0x8D, 0x7E, 0xE8, 0x98, 0x30, 0xFF, 0x6F, 0xB2, 0xBD, 0x03, 0x35, 0x71,
0xD3, 0xF6, 0x08, 0x0F, 0x2D, 0x72, 0x31, 0x49, 0xD9, 0x9F, 0xEB, 0x32,
0x72, 0xDC, 0xE0, 0x59, 0xF8, 0xE2, 0xAA, 0xBB, 0x94, 0x48, 0xE3, 0x65,
0x89, 0x2B, 0xB6, 0xA4, 0xCA, 0x38, 0x39, 0x82, 0x92, 0x1D, 0xED, 0x9E,
0x8D, 0x7E, 0xE8, 0x98, 0x30, 0xFF, 0x6F, 0xB2, 0xBD, 0x03, 0x35, 0x71,
0xD3, 0xF6, 0x08, 0x0F, 0xE3, 0xAB, 0xE2, 0x85, 0x50, 0x08, 0xD1, 0xA8,
0x27, 0x88, 0x2D, 0x92, 0x65, 0x5D, 0x30, 0xBF, 0xA1, 0x61, 0x69, 0xA1,
0x32, 0xAC, 0xC0, 0x68, 0x55, 0x5A, 0x82, 0x98, 0x2C, 0x2C, 0x02, 0x64,
0x8D, 0x7E, 0xE8, 0x98, 0x30, 0xFF, 0x6F, 0xB2, 0xBD, 0x03, 0x35, 0x71,
0xD3, 0xF6, 0x08, 0x0F, 0x8D, 0x7E, 0xE8, 0x98, 0x30, 0xFF, 0x6F, 0xB2,
0xBD, 0x03, 0x35, 0x71, 0xD3, 0xF6, 0x08, 0x0F, 0xAD, 0xF6, 0x5C, 0x7E,
0xC3, 0x7B, 0x8A, 0x5C, 0xC3, 0xF6, 0x40, 0x28, 0x0F, 0x4E, 0x30, 0x0F,
0x8D, 0x7E, 0xE8, 0x98, 0x30, 0xFF, 0x6F, 0xB2, 0xBD, 0x03, 0x35, 0x71,
0xD3, 0xF6, 0x08, 0x0F, 0xFF, 0x1D, 0x50, 0x0E, 0xFE, 0x67, 0xF3, 0x44,
0x9C, 0xDF, 0xEE, 0xC2, 0x4A, 0xFB, 0xCA, 0x04, 0x96, 0x16, 0x10, 0xF1,
0x30, 0x17, 0x4E, 0x7F, 0x4C, 0xF8, 0x86, 0x53, 0x7C, 0x73, 0x15, 0x0A,
0x8D, 0x7E, 0xE8, 0x98, 0x30, 0xFF, 0x6F, 0xB2, 0xBD, 0x03, 0x35, 0x71,
0xD3, 0xF6, 0x08, 0x0F, 0xF4, 0xAD, 0x23, 0x55, 0x42, 0x96, 0xED, 0xC0,
0x71, 0x75, 0x9B, 0x1C, 0x70, 0x17, 0x07, 0x25, 0x0A, 0x83, 0x42, 0xEB,
0x81, 0xAB, 0x4B, 0x1B, 0xE5, 0x39, 0xA0, 0x9E, 0x98, 0xD7, 0x33, 0x67,
0x3E, 0xF0, 0xFA, 0xBB, 0xB7, 0xBD, 0x71, 0xD1, 0x4D, 0x11, 0x52, 0xC3,
0x2B, 0x9C, 0xDA, 0x43, 0xA3, 0x48, 0xEB, 0x27, 0x04, 0x0E, 0x6E, 0x0D,
0xF6, 0x42, 0xA5, 0xB7, 0xB3, 0xC5, 0x78, 0x45, 0xD8, 0x28, 0xCE, 0x52,
0x22, 0xC5, 0x82, 0x0F, 0x1F, 0xA9, 0x0F, 0xCE, 0xD9, 0xD2, 0x1F, 0xA5,
0x8A, 0xFE, 0x93, 0xBC, 0x02, 0x18, 0x2F, 0x7C, 0x27, 0x5C, 0x67, 0xC1,
0xE0, 0xF6, 0xBD, 0x94, 0x8D, 0x7E, 0xE8, 0x98, 0x30, 0xFF, 0x6F, 0xB2,
0xBD, 0x03, 0x35, 0x71, 0xD3, 0xF6, 0x08, 0x0F, 0x53, 0xF1, 0x82, 0xF9,
0xDF, 0x59, 0xF3, 0x3C, 0xA8, 0xAF, 0x18, 0x68, 0xFF, 0xD8, 0x1B, 0x19,
0x19, 0xCF, 0x42, 0xEB, 0xE2, 0xC5, 0x6B, 0x22, 0x90, 0x4A, 0x34, 0xE3,
0x36, 0x8A, 0x49, 0xE1, 0xEA, 0x79, 0xFA, 0x1F, 0x79, 0x8A, 0x3C, 0xE3,
0xC4, 0x8C, 0x46, 0x49, 0x56, 0x7B, 0x80, 0x8F, 0x8D, 0x7E, 0xE8, 0x98,
0x30, 0xFF, 0x6F, 0xB2, 0xBD, 0x03, 0x35, 0x71, 0xD3, 0xF6, 0x08, 0x0F,
0xF9, 0x85, 0x6C, 0xC3, 0x6E, 0x9A, 0x3D, 0x9C, 0x3D, 0xAC, 0xD0, 0x9C,
0x11, 0x8F, 0x82, 0x1C, 0x45, 0xC6, 0xF3, 0xE6, 0xD6, 0x12, 0x6A, 0xFC,
0x3D, 0x61, 0x6C, 0xED, 0xBB, 0x7A, 0x08, 0xB5, 0x13, 0x9D, 0x43, 0x91,
0x75, 0x69, 0x20, 0x4D, 0xE2, 0xBE, 0xA7, 0x30, 0x93, 0xF7, 0xA7, 0xC1,
0x5A, 0x6C, 0x35, 0x53, 0x86, 0x03, 0x32, 0x26, 0x6B, 0xD8, 0xD8, 0xA7,
0xDC, 0xE7, 0xF3, 0x42, 0x8D, 0x7E, 0xE8, 0x98, 0x30, 0xFF, 0x6F, 0xB2,
0xBD, 0x03, 0x35, 0x71, 0xD3, 0xF6, 0x08, 0x0F, 0xBE, 0x85, 0x0C, 0x45,
0x9E, 0x70, 0xC6, 0x84, 0x15, 0xA3, 0xC4, 0x2E, 0x60, 0xAD, 0xC9, 0xB9,
0x99, 0x95, 0x4A, 0xBD, 0xD9, 0x43, 0xA5, 0x56, 0x28, 0xE9, 0xCF, 0x96,
0x8A, 0x05, 0x40, 0xCF, 0x34, 0x64, 0x71, 0x69, 0xCA, 0x92, 0x9F, 0x1F,
0x01, 0x48, 0xDB, 0xFD, 0x73, 0x29, 0x41, 0x94, 0x9A, 0x92, 0xEF, 0x74,
0x71, 0xA5, 0xE0, 0xF9, 0x7D, 0x11, 0xCF, 0x6B, 0x5A, 0x81, 0x74, 0x77,
0x1D, 0x25, 0xC1, 0x18, 0x9B, 0xDE, 0xF3, 0x88, 0x18, 0x88, 0x2B, 0x3A,
0xD7, 0xD4, 0xDA, 0x57, 0xF6, 0xE0, 0xE1, 0xCC, 0xD2, 0x83, 0x61, 0xEA,
0xDF, 0xBE, 0xC6, 0xEE, 0x82, 0x29, 0x31, 0x03, 0xC3, 0xB7, 0x44, 0xD2,
0x8A, 0x00, 0x1E, 0x4F, 0x40, 0x74, 0x56, 0x72, 0xCA, 0x4F, 0xAD, 0x44,
0x6C, 0x20, 0xD7, 0xA3, 0xA2, 0xF4, 0xDA, 0x32, 0x51, 0xCE, 0xAA, 0x8D,
0x7F, 0xD1, 0xD1, 0xFB, 0xC0, 0xA3, 0x3E, 0xB9, 0xB4, 0x8E, 0x54, 0xDA,
0xE9, 0x7A, 0xD6, 0xBA, 0xFD, 0x54, 0xB7, 0x50, 0x2D, 0x02, 0xA4, 0xC9,
0x8A, 0x1E, 0x82, 0xB5, 0x11, 0x8E, 0x38, 0xAA, 0xDE, 0x2F, 0x84, 0x64,
0x44, 0x03, 0xA6, 0xF9, 0x4C, 0xD7, 0x6A, 0x8F, 0x25, 0x6F, 0xD6, 0x7B,
0xF8, 0x47, 0x71, 0x33, 0x28, 0x2A, 0x25, 0x01, 0x1D, 0xEA, 0x8C, 0xBA,
0x62, 0x65, 0xE0, 0x5B, 0x5E, 0xA8, 0x6F, 0x5F, 0xEE, 0xA9, 0x09, 0x6B,
0xB2, 0x35, 0xBB, 0x07, 0x40, 0x8A, 0x99, 0xB9, 0xBB, 0xDE, 0xEB, 0x7B,
0x92, 0x73, 0xC5, 0x7A, 0x5E, 0x71, 0xA9, 0x5A, 0x3A, 0xC1, 0x76, 0x74,
0x4F, 0x0C, 0x37, 0x9A, 0x9C, 0x66, 0xDE, 0x41, 0x40, 0xB3, 0xBF, 0x58,
0x25, 0x88, 0x05, 0x0B, 0x3B, 0x62, 0x06, 0x89, 0x12, 0x5E, 0x2C, 0x82,
0x7E, 0x18, 0x93, 0x60, 0xAE, 0x71, 0x6A, 0x79, 0x1C, 0x5F, 0xB6, 0x70,
0x7C, 0xEF, 0x16, 0x3E, 0x6C, 0x9F, 0x88, 0x0F, 0x6C, 0x39, 0xE9, 0xED,
0xCB, 0x01, 0x3C, 0x27, 0x08, 0x78, 0xFA, 0x60, 0xB5, 0xD4, 0x14, 0xAB,
0x10, 0xB0, 0xE4, 0xA2, 0x8F, 0x80, 0x4F, 0x6E, 0xB7, 0x45, 0xCB, 0x81,
0x84, 0x86, 0x83, 0xFE, 0x15, 0x8B, 0x21, 0x59, 0xD7, 0x83, 0x2A, 0x4F,
0x68, 0x5B, 0x61, 0xC1, 0x49, 0x55, 0xA4, 0xB3, 0x03, 0xD8, 0x2C, 0x7F,
0x2F, 0xDD, 0xED, 0x8E, 0xD0, 0xF2, 0xBD, 0x12, 0x4D, 0x1E, 0x53, 0x4B,
0x1D, 0x5F, 0x08, 0x25, 0x9B, 0x3D, 0xA2, 0xA1, 0xEA, 0x44, 0x99, 0x6D,
0x71, 0x3B, 0x48, 0x49, 0xFD, 0x2E, 0x5A, 0x71, 0xEC, 0xA0, 0x86, 0x13,
0x26, 0x02, 0x0B, 0x49, 0xF8, 0x10, 0xD6, 0x60, 0xAA, 0x6B, 0x02, 0xDF,
0xE5, 0xAA, 0xBA, 0x26, 0xFA, 0xCD, 0x50, 0xDE, 0xE3, 0x31, 0x93, 0x53,
0x4E, 0x0F, 0x65, 0x77, 0xF9, 0xBF, 0x29, 0x95, 0x86, 0xB9, 0x7E, 0x83,
0x45, 0xDB, 0xF2, 0x4A, 0x05, 0x3C, 0x2D, 0xDD, 0x58, 0x6A, 0xEA, 0xFE,
0x53, 0x77, 0x7F, 0x2F, 0x05, 0xF7, 0x29, 0x3C, 0x17, 0x69, 0x36, 0xB8,
0xDB, 0x33, 0x13, 0x8D, 0x76, 0xFD, 0xA5, 0xBC, 0x65, 0xAE, 0xFD, 0xC7,
0xED, 0x48, 0xC9, 0x4C, 0x30, 0x40, 0xD6, 0x38, 0x5A, 0xCE, 0x1A, 0x04,
0x8F, 0xF8, 0xEE, 0x44, 0x60, 0xAD, 0x3A, 0x94, 0xA3, 0x8C, 0x26, 0x63,
0x5B, 0xC1, 0x18, 0xC6, 0x73, 0x7F, 0x12, 0x20, 0x04, 0xB5, 0x67, 0x5A,
0x29, 0xB5, 0xE9, 0x8D, 0x28, 0x92, 0x05, 0xDA, 0x67, 0xA4, 0x9F, 0xB8,
0xCC, 0x35, 0x0F, 0x2B, 0xF1, 0xB9, 0x50, 0x46, 0xEF, 0xA0, 0x7D, 0xC6,
0x42, 0xEA, 0x38, 0x4E, 0xE8, 0xB4, 0xE2, 0xB1, 0x4C, 0x65, 0x18, 0xD7,
0x18, 0x73, 0xD9, 0x6D, 0x28, 0x24, 0x6D, 0xEB, 0x4D, 0xF7, 0xBD, 0x31,
0xAC, 0x8C, 0x80, 0xC6, 0xF8, 0x72, 0x5B, 0xAE, 0xF0, 0x16, 0x88, 0x25,
0x9A, 0xEF, 0xB2, 0xE5, 0x8E, 0xAD, 0xD0, 0xC2, 0x8D, 0x96, 0x80, 0xB6,
0x00, 0xD0, 0x08, 0x2C, 0x8C, 0xE1, 0x0D, 0xC3, 0x57, 0xC0, 0x2B, 0xF7,
0xA5, 0x5A, 0x82, 0xFF, 0x69, 0xAD, 0x01, 0xE6, 0x42, 0xCD, 0x38, 0x4D,
0x4E, 0xB6, 0x6D, 0xC6, 0xA4, 0x6A, 0x53, 0x5C, 0x13, 0x92, 0x05, 0x36,
0x02, 0xB3, 0x98, 0x8E, 0x9E, 0xBB, 0x48, 0x74, 0xE3, 0x2E, 0x86, 0x84,
0xFF, 0x80, 0xB4, 0xEE, 0x94, 0x3F, 0xBB, 0x37, 0xD7, 0xC3, 0xA8, 0x4B,
0x5A, 0x85, 0x5A, 0x6A, 0xB7, 0x4D, 0x4B, 0xB3, 0x47, 0x6F, 0x6C, 0x43,
0xBA, 0x12, 0x38, 0x61, 0xA1, 0x61, 0x2C, 0x7B, 0x50, 0xFA, 0x3A, 0x05,
0x4C, 0x16, 0x0E, 0x2F, 0x88, 0x6C, 0xCF, 0xAC, 0x4F, 0xB7, 0xD9, 0x0E,
0xC7, 0x55, 0x72, 0x9D, 0xF5, 0x64, 0xC4, 0xB8, 0x9A, 0x82, 0x18, 0xDA,
0x51, 0x2C, 0x7F, 0x39, 0xC1, 0x17, 0xB9, 0xF4, 0x2F, 0x98, 0x3B, 0x55,
0x7B, 0x69, 0xCC, 0x83, 0xE3, 0xDE, 0x75, 0x44, 0xFD, 0x55, 0x06, 0x73,
0x47, 0xC7, 0xEE, 0x47, 0xA2, 0x3B, 0x35, 0x17, 0xF0, 0xF3, 0x0B, 0xE8,
0x01, 0x97, 0x77, 0x67, 0x28, 0x14, 0xA4, 0x3F, 0x96, 0x74, 0xA2, 0xA4,
0x35, 0xE3, 0x1F, 0x69, 0x41, 0x5A, 0x89, 0x4F, 0x19, 0x06, 0xDF, 0xD7,
0x57, 0xC0, 0x54, 0x27, 0x72, 0x0F, 0x36, 0xE0, 0xF9, 0x57, 0xC0, 0x9A,
0x56, 0xFD, 0x5C, 0x19, 0xC5, 0x79, 0x50, 0x88, 0xB8, 0x70, 0x57, 0xDB,
0x55, 0x98, 0xA8, 0x2F, 0xBB, 0xB8, 0xAF, 0xF8, 0xE5, 0x33, 0x0D, 0x40,
0xBE, 0xBC, 0x3C, 0x7E, 0xC8, 0xFF, 0x11, 0x7C, 0x12, 0x39, 0x76, 0x12,
0x9C, 0x8D, 0x9C, 0x95, 0x23, 0x6A, 0x1A, 0xE9, 0xAF, 0xD7, 0x9B, 0xD1,
0x8E, 0xA1, 0x32, 0x2F, 0x17, 0x4D, 0x84, 0x9C, 0xCC, 0x8F, 0xA9, 0x14,
0xEC, 0x86, 0xCF, 0x1A, 0xFD, 0x1D, 0x45, 0x14, 0x5D, 0x9B, 0x0C, 0x63,
0x3A, 0xF2, 0x84, 0x44, 0xAA, 0x4D, 0x69, 0x76, 0x15, 0x32, 0xD2, 0xCB,
0x6B, 0x03, 0x30, 0x9A, 0x6A, 0x64, 0x66, 0x8C, 0x06, 0xEC, 0x70, 0xCC,
0x33, 0x92, 0xAA, 0x43, 0x09, 0x06, 0xE2, 0x52, 0x48, 0xE1, 0x76, 0x09,
0x0F, 0x44, 0x7B, 0x40, 0x04, 0x7B, 0xD7, 0xBD, 0x8C, 0xEC, 0xBD, 0x8E,
0x16, 0xBF, 0x2F, 0x40, 0x48, 0x72, 0x78, 0xA0, 0x45, 0x16, 0x90, 0x37,
0xAA, 0x7A, 0xCA, 0x8F, 0x7A, 0x6C, 0xAA, 0x68, 0xB3, 0xEB, 0x63, 0xE9,
0x7F, 0xD0, 0xE7, 0x3A, 0x82, 0xFF, 0xEB, 0x45, 0x7F, 0x75, 0xDC, 0xB5,
0xF9, 0x6A, 0x27, 0x8E, 0x49, 0x39, 0x0A, 0xAE, 0x98, 0x24, 0xC4, 0xEE,
0xF5, 0x80, 0xBC, 0xF5, 0x30, 0x4F, 0x7D, 0x5A, 0x0C, 0x79, 0x0F, 0x37,
0x3D, 0x9C, 0x53, 0xD6, 0xEE, 0x95, 0xEA, 0x85, 0x54, 0xE6, 0x9A, 0x2A,
0xCF, 0x80, 0xDC, 0x14, 0x76, 0x8D, 0x9C, 0x83, 0x1F, 0x40, 0xAC, 0x66,
0x27, 0x67, 0x69, 0xB6, 0xBC, 0x05, 0x7E, 0xE9, 0xC6, 0xCE, 0xB2, 0xD6,
0xB1, 0xAC, 0x79, 0x20, 0x13, 0x24, 0xCE, 0xC4, 0xD1, 0x02, 0x6B, 0x88,
0xD4, 0x0D, 0xD9, 0x41, 0x9D, 0x94, 0x71, 0xF2, 0x06, 0x15, 0xDF, 0x34,
0xF1, 0x4D, 0xB3, 0x02, 0x84, 0xAE, 0x83, 0x7D, 0xDC, 0xC8, 0xC3, 0x3E,
0x53, 0x01, 0x5C, 0x1D, 0xB0, 0xFE, 0x84, 0xA3, 0x73, 0xA9, 0x6A, 0x8A,
0x13, 0xD3, 0xEF, 0x8B, 0xEA, 0x90, 0x78, 0x87, 0xB5, 0xFF, 0xCE, 0x34,
0xF9, 0x78, 0x7B, 0xAD, 0xB8, 0x62, 0xDE, 0xB5, 0xB5, 0x6C, 0xF9, 0xB3,
0x67, 0x2E, 0x83, 0x9D, 0x52, 0xBE, 0x44, 0xD1, 0x89, 0xD6, 0x2B, 0xE4,
0x58, 0x67, 0x9D, 0xAC, 0xC4, 0x25, 0xEB, 0x50, 0x20, 0x1F, 0x2E, 0xF5,
0xE7, 0x38, 0x05, 0xEF, 0x70, 0x9C, 0xF3, 0x0C, 0x4A, 0xB4, 0x47, 0xD4,
0x1C, 0x89, 0x9C, 0xD3, 0x09, 0x6A, 0x97, 0xCC, 0xF3, 0xC6, 0x85, 0x4A,
0xB3, 0x0F, 0xAF, 0xF0, 0x0A, 0xC0, 0x40, 0xE0, 0x22, 0x19, 0xEB, 0x81,
0x63, 0x3E, 0x5D, 0x36, 0x28, 0x63, 0xCD, 0x48, 0xBB, 0xB5, 0x3F, 0x52,
0xD2, 0xAB, 0x27, 0x01, 0xC4, 0x75, 0x67, 0xF5, 0xC2, 0x89, 0x43, 0x48,
0xCF, 0x4B, 0x8C, 0xB2, 0xED, 0x11, 0x87, 0x5F, 0x16, 0xFF, 0xC7, 0xDC,
0x77, 0x4A, 0xFE, 0xEA, 0xEE, 0xC4, 0x9D, 0x9F, 0xB4, 0xA2, 0x3A, 0x01,
0xD3, 0x20, 0xEB, 0x95, 0x84, 0xAD, 0x4C, 0xCC, 0xD9, 0x12, 0xA1, 0x4B,
0xC7, 0xC3, 0x60, 0x26, 0xBA, 0xDB, 0x26, 0x9F, 0xF1, 0x3A, 0x66, 0xE1,
0x8C, 0x06, 0xD1, 0x47, 0x0B, 0x77, 0x84, 0xAA, 0xEE, 0x8A, 0x3F, 0xCB,
0x51, 0x8E, 0x15, 0x71, 0xB7, 0x45, 0x79, 0x8C, 0x34, 0xC3, 0xB2, 0x56,
0xE5, 0xC4, 0x24, 0xAF, 0x05, 0x3F, 0x56, 0x86, 0x87, 0xAE, 0xA2, 0x96,
0xA4, 0x78, 0xB2, 0x29, 0x34, 0xA5, 0xE3, 0x02, 0x52, 0x5A, 0xD6, 0x5F,
0x8F, 0xE7, 0x55, 0xE8, 0x89, 0xCA, 0x1F, 0xDD, 0x29, 0x81, 0x80, 0xBA,
0xA0, 0x0C, 0x28, 0xFA, 0x85, 0x8A, 0xAC, 0xA3, 0x8F, 0x48, 0xB5, 0xC2,
0xB8, 0xD1, 0x87, 0x0F, 0x89, 0x5B, 0xA1, 0x94, 0x2C, 0xE4, 0x05, 0xC6,
0x60, 0x94, 0x57, 0xC2, 0x69, 0x53, 0x01, 0xA9, 0xEF, 0xC4, 0x3D, 0x92,
0x21, 0x0D, 0x78, 0x2C, 0xFE, 0x58, 0x65, 0xBB, 0xB7, 0x0A, 0x39, 0x6A,
0x20, 0xC4, 0xAE, 0x4B, 0xF0, 0x57, 0xEE, 0x0A, 0x59, 0xA0, 0x71, 0xD1,
0xBF, 0xB9, 0x39, 0xC7, 0x12, 0x3C, 0xAA, 0xCA, 0xFB, 0xCE, 0x0F, 0x43,
0x48, 0xDD, 0xA7, 0xB5, 0x0D, 0x25, 0xF3, 0x88, 0xA7, 0xD4, 0xDA, 0xDC,
0x6B, 0xBE, 0x18, 0x36, 0x09, 0x82, 0xE8, 0x99, 0x74, 0xD1, 0x83, 0xFF,
0x94, 0x2B, 0xA5, 0xD9, 0xC0, 0x8E, 0xBF, 0x0C, 0xF3, 0xAF, 0xCE, 0x06,
0x4B, 0x86, 0x4D, 0x2E, 0xB8, 0xAA, 0x0C, 0xA5, 0x0C, 0xC3, 0x38, 0xA8,
0x60, 0x0E, 0xD9, 0x58, 0x71, 0x10, 0x00, 0x37, 0x99, 0x81, 0x9D, 0xB8,
0x4F, 0xEF, 0x74, 0xAC, 0x37, 0xBC, 0x57, 0x53, 0x4E, 0xAF, 0xAE, 0x87,
0x78, 0xFB, 0x82, 0x18, 0x60, 0x78, 0x99, 0x98, 0x16, 0x01, 0x41, 0x42,
0x5E, 0xDE, 0xDF, 0xA9, 0xBD, 0x7B, 0x93, 0xDC, 0xC4, 0xB8, 0x9F, 0x4E,
0xD5, 0x8A, 0x20, 0x15, 0x49, 0x0C, 0xCF, 0x0A, 0x2E, 0x6E, 0xDE, 0xCB,
0x67, 0x59, 0x1B, 0x1B, 0xB8, 0x24, 0xB0, 0xB0, 0xE4, 0x13, 0x1A, 0x8E,
0x4E, 0x39, 0xF4, 0x52, 0x69, 0xE3, 0xDC, 0x95, 0xC0, 0xC8, 0xC0, 0xB3,
0x96, 0xE2, 0x72, 0x99, 0xA1, 0xE9, 0xFD, 0xC4, 0x9E, 0xFA, 0x43, 0xD3,
0x62, 0x17, 0x6B, 0x54, 0x35, 0x7D, 0xB1, 0xBF, 0xA9, 0xB3, 0x03, 0x18,
0x36, 0x73, 0xE2, 0xC7, 0xC2, 0xD9, 0xB2, 0x35, 0x6B, 0x7D, 0x9F, 0x55,
0x38, 0xF9, 0xA1, 0x61, 0xA0, 0x99, 0x34, 0x02, 0x39, 0x29, 0x21, 0x97,
0xDF, 0x87, 0xDA, 0xCB, 0x87, 0x75, 0x4F, 0xFA, 0x57, 0x54, 0x69, 0x3A,
0x97, 0x24, 0xFE, 0xBE, 0x2F, 0xB4, 0x7B, 0x12, 0xC3, 0xA7, 0x0A, 0xE9,
0x39, 0x9A, 0x2C, 0x08, 0x6A, 0x05, 0x66, 0x0F, 0xD3, 0x38, 0xA5, 0xD9,
0xC8, 0x83, 0x2A, 0x6B, 0xC5, 0x44, 0xE3, 0x7B, 0x01, 0xAB, 0x32, 0x96,
0x8C, 0x23, 0x2A, 0x14, 0x7C, 0x3C, 0xBB, 0x46, 0x51, 0x04, 0x12, 0xB6,
0x1B, 0xB6, 0xE3, 0xF0, 0xAD, 0x23, 0xEB, 0x67, 0xF8, 0xB9, 0x95, 0xC1,
0x98, 0x55, 0xE3, 0x75, 0xA7, 0x1A, 0x7C, 0x3A, 0xB8, 0x9D, 0xA7, 0x12,
0xDF, 0xFC, 0xA0, 0x1A, 0xBB, 0x5C, 0xC8, 0x69, 0x95, 0x5A, 0x67, 0xE3,
0x5A, 0xFC, 0x14, 0x3F, 0x17, 0x6E, 0x54, 0x0A, 0x80, 0xA9, 0x51, 0xE8,
0x41, 0x20, 0xFD, 0x58, 0x12, 0x31, 0x45, 0xD3, 0x50, 0xF4, 0x46, 0x67,
0x75, 0x4B, 0x21, 0x3C, 0x57, 0x6D, 0xDD, 0x7C, 0xAC, 0xE0, 0xA7, 0x86,
0xC9, 0xF8, 0xA7, 0x09, 0xB5, 0x45, 0x1C, 0xE9, 0xD5, 0xB5, 0xC0, 0xC5,
0x67, 0x2F, 0xE9, 0x34, 0xA1, 0x0D, 0xCD, 0xB4, 0xE5, 0x3D, 0xB2, 0x41,
0x9C, 0x72, 0x4C, 0x88, 0x22, 0x0F, 0x48, 0xE6, 0x78, 0x3C, 0xCD, 0xEF,
0x06, 0x70, 0x10, 0xBF, 0x66, 0x14, 0xE0, 0xA9, 0x2F, 0xBA, 0xF5, 0x96,
0x47, 0xB0, 0x79, 0x59, 0x98, 0x0A, 0x9B, 0x16, 0xD3, 0xB1, 0x11, 0xB1,
0xBD, 0xDA, 0x81, 0xDB, 0x4F, 0x56, 0xBC, 0x68, 0x15, 0xA8, 0xBA, 0x10,
0x0B, 0xD1, 0xBE, 0x76, 0x2C, 0x4D, 0xA8, 0x4F, 0x3F, 0xC8, 0x9E, 0xA5,
0xAE, 0x88, 0x6B, 0x7D, 0x11, 0xFE, 0x89, 0xFC, 0x17, 0x0F, 0x0C, 0x32,
0x51, 0xF4, 0xDB, 0x3E, 0x94, 0x55, 0xC6, 0xDA, 0xED, 0xD5, 0x0F, 0x87,
0xB9, 0x7F, 0x33, 0xC3, 0xD1, 0x0B, 0x83, 0x63, 0x32, 0x72, 0x36, 0xED,
0xA1, 0x2A, 0xF8, 0x6E, 0x88, 0x42, 0xC4, 0x94, 0xBB, 0x00, 0x64, 0xC1,
0x72, 0x25, 0x36, 0x53, 0xBB, 0x71, 0x02, 0x68, 0x78, 0xC1, 0x7A, 0x5F,
0x70, 0xD0, 0x8D, 0x15, 0x94, 0xC0, 0x90, 0xA7, 0x81, 0x4F, 0x87, 0x30,
0x49, 0x44, 0xC8, 0x96, 0xED, 0x9C, 0x6E, 0xD4, 0x9D, 0x2A, 0x81, 0x73,
0xD3, 0x89, 0x8C, 0x32, 0x3C, 0xAD, 0xAC, 0x0B, 0x99, 0x7A, 0xD8, 0x25,
0x94, 0x77, 0xB0, 0x21, 0x24, 0x4E, 0xE6, 0x47, 0x6C, 0xB1, 0x6B, 0x87,
0xF9, 0x76, 0x95, 0x65, 0x2D, 0x05, 0x03, 0x55, 0x24, 0x1F, 0x6B, 0xAF,
0xC2, 0x6B, 0x17, 0xAC, 0x5F, 0x0C, 0x74, 0x06, 0xAB, 0xDD, 0x04, 0x30,
0xC8, 0xD6, 0x4F, 0xD1, 0xE8, 0xA2, 0xF4, 0xB1, 0xE0, 0x47, 0x19, 0x00,
0x13, 0x83, 0x87, 0xEB, 0xC7, 0xD9, 0xAB, 0x6C, 0x57, 0xDA, 0x00, 0xD4,
0x9D, 0x4D, 0x6D, 0x66, 0xC7, 0x51, 0xB5, 0xCF, 0x1F, 0x91, 0x04, 0x16,
0x30, 0xCC, 0xCE, 0x7B, 0xD2, 0x69, 0x77, 0xED, 0xCC, 0x07, 0x6D, 0xEB,
0x63, 0x2B, 0x99, 0x16, 0x14, 0x1E, 0x0D, 0x1D, 0xDA, 0x2C, 0x98, 0x16,
0xDF, 0xDC, 0xD4, 0x92, 0xD3, 0xCC, 0x6A, 0x35, 0x80, 0xF1, 0xCC, 0x0F,
0xF1, 0xF7, 0x43, 0xE6, 0x82, 0xC6, 0xF5, 0x6A, 0x2D, 0x16, 0xCC, 0xFB,
0x28, 0x23, 0xE0, 0x27, 0xB5, 0xC1, 0x83, 0x88, 0x17, 0xB2, 0x9E, 0x24,
0xBD, 0xA6, 0x17, 0x3B, 0xBD, 0xF8, 0xFB, 0x96, 0xC4, 0x77, 0x93, 0x2E,
0x51, 0x45, 0xB1, 0x45, 0x97, 0x3A, 0x08, 0x78, 0xA0, 0x34, 0x6B, 0x4B,
0x5C, 0xDF, 0xFE, 0x40, 0x04, 0x8A, 0xE9, 0xFB, 0xCC, 0x6C, 0xD6, 0x56,
0x28, 0x89, 0x7F, 0xDE, 0x2A, 0xC3, 0xD9, 0x92, 0x8F, 0x22, 0x03, 0x1B,
0xEA, 0x22, 0xAB, 0x99, 0x18, 0x5B, 0x47, 0xC3, 0x06, 0x02, 0xBC, 0xBB,
0x42, 0xB4, 0x2C, 0x05, 0x61, 0x97, 0x86, 0x9B, 0x77, 0x91, 0x5B, 0x48,
0xAC, 0x68, 0x23, 0x01, 0x62, 0x7F, 0xA5, 0x7F, 0xF0, 0x7B, 0x6F, 0x04,
0x37, 0x91, 0x13, 0xF4, 0xEB, 0x3C, 0x2E, 0x2C, 0x9A, 0xE6, 0x1F, 0xB1,
0x5F, 0xAF, 0xD4, 0x8A, 0xDB, 0x77, 0xCC, 0x0A, 0xA7, 0x7C, 0xC4, 0x46,
0x02, 0xA5, 0x8F, 0x81, 0xEF, 0x92, 0x39, 0xB0, 0x8C, 0xEA, 0xFA, 0x4C,
0x77, 0x30, 0x21, 0xE8, 0x6D, 0xA0, 0x4C, 0x0A, 0x65, 0xFA, 0x20, 0xD1,
0x7F, 0xCE, 0x69, 0x11, 0x1F, 0x63, 0xFB, 0x70, 0xCB, 0x42, 0xE1, 0xB5,
0x09, 0xB2, 0x02, 0x83, 0x67, 0xE8, 0x60, 0x20, 0x34, 0x7A, 0x59, 0xC0,
0x7A, 0x7A, 0xC1, 0x8D, 0x83, 0x0E, 0x90, 0x3A, 0x72, 0xAF, 0x6C, 0x9F,
0xA5, 0x95, 0x1B, 0x1D, 0x2D, 0x98, 0x52, 0xDF, 0xCF, 0x55, 0x2A, 0xAD,
0x13, 0xD2, 0x38, 0xA5, 0x66, 0xBC, 0x69, 0xA0, 0xA3, 0x37, 0x7D, 0x0D,
0x70, 0x63, 0x17, 0x49, 0x43, 0xA1, 0x0D, 0xDA, 0xAE, 0xD1, 0x02, 0xFC,
0x0F, 0x6E, 0x7F, 0x26, 0xD8, 0x4C, 0x16, 0xAB, 0xB8, 0x6A, 0x64, 0x03,
0x69, 0xF4, 0x32, 0x69, 0xCD, 0x17, 0x85, 0xF9, 0xCE, 0xD2, 0xBE, 0xAE,
0x9C, 0x59, 0xD8, 0x50, 0xF1, 0x93, 0x1C, 0x06, 0xC6, 0x32, 0x61, 0xC2,
0x54, 0x85, 0x88, 0xF3, 0x77, 0xFD, 0xA3, 0x8D, 0x82, 0x94, 0x63, 0xB4,
0xCA, 0x4C, 0x47, 0xE5, 0xB1, 0x02, 0xA4, 0x53, 0xBB, 0xDF, 0x43, 0xE7,
0x72, 0xD7, 0xE1, 0xD0, 0x18, 0x06, 0xCE, 0x63, 0x63, 0x8A, 0x96, 0xAF,
0x1F, 0xEA, 0xCD, 0x9B, 0x74, 0x21, 0xEA, 0x52, 0x7A, 0xDE, 0xBA, 0x98,
0xA7, 0xAE, 0x01, 0x9A, 0xD5, 0x94, 0xF7, 0x07, 0x6F, 0x46, 0x49, 0xE8,
0x08, 0xEB, 0xA7, 0x4A, 0x6D, 0xF0, 0xC6, 0xFD, 0x9E, 0x64, 0xFB, 0xDB,
0x47, 0x0A, 0x22, 0xB5, 0x93, 0xF3, 0x5C, 0xA4, 0xF7, 0xEE, 0x5E, 0x8C,
0xBD, 0x15, 0x06, 0x65, 0xDA, 0xBE, 0xF5, 0xA1, 0x70, 0x18, 0x1B, 0x36,
0x91, 0x34, 0x65, 0x7B, 0xE2, 0x20, 0xA9, 0xA2, 0x4B, 0x9E, 0xBC, 0x7F,
0xAE, 0x5C, 0xCE, 0x58, 0xC6, 0x5F, 0x0B, 0x30, 0x73, 0xB6, 0xD4, 0x92,
0xD9, 0x85, 0xFE, 0x64, 0x53, 0xD4, 0x03, 0xAF, 0x6B, 0x5E, 0x46, 0x69,
0x5A, 0xEC, 0x65, 0x73, 0xCD, 0x98, 0xE1, 0x11, 0x9C, 0x24, 0xE1, 0xCD,
0x81, 0x7D, 0x91, 0xF9, 0xD3, 0x86, 0x9E, 0xA7, 0x38, 0x00, 0xA0, 0x98,
0x21, 0xD7, 0x4A, 0x1D, 0x86, 0xF4, 0x4E, 0x96, 0x34, 0x8E, 0x9F, 0x25,
0x3D, 0x95, 0xA3, 0xD8, 0xB7, 0x7A, 0xFD, 0xB0, 0xA5, 0xC8, 0x31, 0x73,
0xA1, 0x91, 0x33, 0x34, 0x88, 0xAA, 0xFB, 0xB8, 0x56, 0x2A, 0xE3, 0xD6,
0xA7, 0x9C, 0x98, 0x4B, 0x4B, 0xDC, 0x6D, 0xC5, 0x29, 0xA4, 0xC0, 0xC8,
0x11, 0xCD, 0x1E, 0x19, 0x6B, 0x9E, 0x82, 0x09, 0x90, 0x48, 0xAF, 0xDE,
0x08, 0xBD, 0xBD, 0xC0, 0x5F, 0x9B, 0xB2, 0x22, 0x1A, 0xBD, 0xD7, 0x0F,
0x9D, 0x1C, 0x34, 0xFA, 0xA2, 0xFC, 0x96, 0xE0, 0x47, 0xA7, 0x1A, 0xC1,
0x29, 0xBA, 0x3D, 0xCC, 0x3B, 0x5F, 0x84, 0xCF, 0x24, 0x27, 0x1C, 0x39,
0x3D, 0xB3, 0x99, 0xD1, 0x06, 0x31, 0x7B, 0x55, 0xB8, 0x1B, 0x46, 0x35,
0x9B, 0x77, 0x21, 0xEC, 0x8F, 0x31, 0x9C, 0x8F, 0xA8, 0x97, 0xE9, 0x08,
0xC3, 0x86, 0xB4, 0xF0, 0x98, 0x2C, 0xF1, 0xEF, 0x96, 0x52, 0x3A, 0xC5,
0x9C, 0x91, 0x75, 0xD4, 0x5F, 0xC1, 0x78, 0x79, 0x1A, 0x7A, 0xC8, 0x9A,
0x10, 0x40, 0x7A, 0xFE, 0xAF, 0x28, 0x63, 0x5E, 0xF6, 0x10, 0x42, 0xC6,
0xC5, 0x2D, 0x79, 0x8C, 0xB2, 0x54, 0x2E, 0xFE, 0x25, 0x7F, 0x12, 0x69,
0x47, 0xD9, 0x71, 0x97, 0xF5, 0xA9, 0xC8, 0x0C, 0x9A, 0x28, 0x1F, 0xDE,
0xFB, 0xD9, 0xDC, 0x79, 0xD8, 0x6E, 0x70, 0xFD, 0x74, 0x20, 0xD5, 0xC9,
0x51, 0xCF, 0xC3, 0x2D, 0x57, 0xA9, 0xEE, 0x65, 0xAA, 0xC3, 0x17, 0xD6,
0x21, 0xBA, 0xFA, 0x43, 0x53, 0xD2, 0x84, 0x86, 0x0C, 0xD5, 0x51, 0x48,
0x64, 0x40, 0x76, 0x47, 0x1D, 0xD5, 0xEF, 0x24, 0x71, 0x85, 0xFC, 0xF7,
0xCB, 0xCA, 0xE5, 0x3E, 0x56, 0x39, 0x22, 0x50, 0x4F, 0xAF, 0x5D, 0x3A,
0xE2, 0xE4, 0x09, 0x3B, 0x68, 0xCC, 0xFE, 0xD5, 0x0C, 0x9D, 0xBB, 0xD2,
0x16, 0xA1, 0xA5, 0x82, 0x8D, 0x7B, 0xAC, 0xEF, 0x7A, 0xE2, 0x88, 0xB6,
0x19, 0x8F, 0x24, 0x1E, 0x53, 0x7A, 0x8C, 0xE9, 0xD3, 0x62, 0xC8, 0x9E,
0xD1, 0x35, 0x60, 0x8E, 0xC3, 0x23, 0xAB, 0x70, 0x83, 0x38, 0xFC, 0xF4,
0x6F, 0xFF, 0x2E, 0x61, 0xDF, 0x07, 0xA8, 0xA4, 0xBE, 0xD3, 0xD7, 0x97,
0x3E, 0x3D, 0xC9, 0xAD, 0xE6, 0xCB, 0x47, 0x09, 0x34, 0xC7, 0x1F, 0xD9,
0x7C, 0xBC, 0xE5, 0xB0, 0xE2, 0x4D, 0x9E, 0x2A, 0xFA, 0xFF, 0x40, 0x30,
0xE5, 0xFE, 0xFF, 0x55, 0x38, 0x26, 0xC5, 0x0E, 0x16, 0xBD, 0x53, 0xC5,
0x24, 0xA7, 0xE0, 0x5A, 0x89, 0xAF, 0x3B, 0x07, 0xA2, 0xF7, 0xCD, 0x42,
0x21, 0x8C, 0x93, 0x34, 0xCF, 0xF3, 0x65, 0x7A, 0x33, 0x1A, 0x8B, 0xE4,
0x57, 0x54, 0x9D, 0x1E, 0xCC, 0x38, 0xBE, 0xAC, 0xF2, 0x59, 0x4E, 0x4A,
0x05, 0x9C, 0x64, 0xDC, 0x6E, 0x87, 0x4A, 0x93, 0x94, 0xE6, 0x04, 0x64,
0xBD, 0xEC, 0xA8, 0xC5, 0xCA, 0x8A, 0xBE, 0x34, 0xF4, 0x0B, 0xC1, 0x19,
0x39, 0x59, 0xD7, 0xBD, 0x4B, 0xB2, 0xA3, 0xE7, 0xB7, 0x0E, 0x03, 0xDC,
0x02, 0x03, 0x87, 0x5D, 0xC1, 0xB7, 0x8F, 0xD9, 0x1D, 0xFE, 0xA1, 0xDA,
0x1D, 0x9C, 0x88, 0x60, 0x14, 0xBA, 0xCD, 0xA7, 0x38, 0xFB, 0x36, 0x45,
0xE2, 0xAB, 0x47, 0x17, 0x41, 0x2C, 0x3E, 0x89, 0x2C, 0xA8, 0x79, 0xB2,
0x91, 0x17, 0xEF, 0x63, 0x4D, 0xE8, 0x78, 0xB5, 0xEC, 0xFE, 0x32, 0xCA,
0xCC, 0xE3, 0xD3, 0x7F, 0xD7, 0x93, 0x22, 0xD2, 0x6C, 0xAD, 0xD7, 0xC2,
0xF6, 0x2E, 0x33, 0x7F, 0x4A, 0x7C, 0x99, 0xE5, 0xAB, 0x50, 0x58, 0x4D,
0x4B, 0x38, 0x00, 0x51, 0xF0, 0x9A, 0x39, 0x7E, 0xB6, 0xFE, 0x86, 0xEC,
0x61, 0x22, 0x30, 0x78, 0xE3, 0x86, 0xE0, 0xE7, 0xA4, 0x75, 0x5E, 0xF3,
0x09, 0x5C, 0xC5, 0x5E, 0x57, 0xE0, 0x08, 0xDA, 0x3A, 0x50, 0x10, 0xE3,
0xEF, 0x63, 0xCF, 0x14, 0x45, 0xFF, 0x94, 0xD4, 0x08, 0x0E, 0xD2, 0xA7,
0xE3, 0x49, 0x5B, 0x99, 0xFC, 0x5C, 0x5B, 0x5F, 0x5F, 0xC1, 0x84, 0x2C,
0x4E, 0x42, 0xF5, 0x62, 0x3F, 0xEC, 0x01, 0x6C, 0x65, 0x38, 0x1A, 0xD5,
0xD4, 0x58, 0xA4, 0xC5, 0xEA, 0xF2, 0xB8, 0xF3, 0xBE, 0xD6, 0xA2, 0x27,
0x39, 0x78, 0x7B, 0xB3, 0xF6, 0x49, 0x28, 0x3C, 0x0C, 0xB4, 0x1A, 0x10,
0x14, 0x78, 0xD4, 0xB1, 0x71, 0x5E, 0xFF, 0x6D, 0x12, 0x88, 0xEA, 0xFE,
0xDE, 0xF4, 0xD4, 0xD2, 0xC2, 0x51, 0x23, 0xD2, 0x33, 0x5B, 0xC4, 0x35,
0x8A, 0xA1, 0x6E, 0x39, 0x8C, 0x31, 0x16, 0x76, 0x4A, 0x1B, 0xCB, 0x91,
0x44, 0xFD, 0x64, 0xBB, 0xA6, 0xCB, 0x0A, 0x56, 0xEB, 0x55, 0x8D, 0xEA,
0x94, 0x91, 0xF7, 0x9D, 0xE6, 0x9F, 0x13, 0xC1, 0xB8, 0x1E, 0xBC, 0x1E,
0x8E, 0x2B, 0x3B, 0x87, 0x9A, 0xD8, 0x32, 0xF8, 0xC4, 0xAD, 0x69, 0x08,
0xF9, 0x10, 0xD3, 0x9C, 0x89, 0x03, 0xA8, 0x96, 0xFF, 0x2D, 0x85, 0x81,
0xF4, 0x65, 0x2F, 0x72, 0x60, 0x63, 0x54, 0x5F, 0x97, 0xB6, 0x46, 0xB5,
0xB7, 0x7C, 0xE0, 0x16, 0x61, 0x36, 0x2F, 0x41, 0x4B, 0x81, 0xFE, 0x24,
0x7B, 0xAB, 0x09, 0x34, 0xCD, 0xA0, 0x40, 0x0E, 0xB1, 0xB1, 0x05, 0xA2,
0x88, 0x14, 0x22, 0xE3, 0xCC, 0x45, 0x62, 0xD2, 0x34, 0xC5, 0x9F, 0xEB,
0x36, 0xF4, 0x26, 0x6C, 0xBF, 0x9E, 0xC1, 0x72, 0xF8, 0x6A, 0x23, 0xA7,
0x87, 0xCF, 0xD2, 0x0A, 0x99, 0x37, 0xE5, 0x0D, 0x68, 0x47, 0xAC, 0x4D,
0x52, 0x47, 0x00, 0x53, 0x15, 0x68, 0x43, 0x12, 0x9F, 0x9B, 0xF8, 0xD9,
0xF9, 0x5F, 0x78, 0xAA, 0xB5, 0x41, 0xB9, 0x84, 0x0A, 0x3A, 0xC8, 0x2A,
0x6F, 0xFF, 0x0B, 0xF0, 0xEE, 0xB4, 0xE8, 0xE4, 0x42, 0xCB, 0xBB, 0xDB,
0x46, 0x31, 0xD0, 0x3A, 0xAA, 0x13, 0xB9, 0x9D, 0x98, 0x85, 0xE5, 0x8B,
0x6C, 0xA3, 0xB6, 0xD1, 0x97, 0x6D, 0x81, 0x17, 0xF0, 0x63, 0x65, 0x81,
0x40, 0x25, 0x31, 0xCC, 0xEF, 0x71, 0x56, 0x81, 0xA6, 0x81, 0xCA, 0x43,
0xBB, 0xDC, 0x79, 0xAE, 0x61, 0x0E, 0x99, 0x14, 0xC2, 0x8F, 0xD8, 0x6E,
0x54, 0xC0, 0x71, 0xCF, 0x98, 0x53, 0x0E, 0x0B, 0x64, 0x87, 0x6E, 0x88,
0xF8, 0xA1, 0xC0, 0xB6, 0x30, 0x58, 0x35, 0xEC, 0x60, 0x04, 0x01, 0xC8,
0x73, 0x24, 0xB4, 0xB0, 0x46, 0xAD, 0xC7, 0x4B, 0xFB, 0xEC, 0xC3, 0x0D,
0x86, 0x44, 0x32, 0x07, 0xD1, 0xC9, 0x94, 0xA7, 0xE4, 0x4E, 0xD4, 0xD7,
0x14, 0xFC, 0x9F, 0x7B, 0xD1, 0x3D, 0x94, 0x56, 0xC2, 0x7C, 0xED, 0x62,
0xFD, 0x91, 0x87, 0x08, 0xA2, 0x6B, 0x44, 0xE5, 0x8C, 0x28, 0xAD, 0xF7,
0x45, 0x15, 0xD3, 0x76, 0xAA, 0x29, 0x27, 0x0D, 0xC2, 0x72, 0x93, 0xF0,
0x5A, 0xB8, 0xBE, 0xBB, 0xD4, 0x0E, 0xA7, 0x11, 0x13, 0xFC, 0xAA, 0x47,
0xD2, 0x4D, 0x05, 0x93, 0x1B, 0xBD, 0x3A, 0x01, 0x0E, 0x53, 0x31, 0x33,
0x3C, 0x23, 0x83, 0x8A, 0x65, 0x1E, 0x82, 0x66, 0x3C, 0x0F, 0x65, 0x67,
0x20, 0xAE, 0x3A, 0x5A, 0xF8, 0x4D, 0x8F, 0xA9, 0x7C, 0xA0, 0x26, 0xBD,
0x1F, 0xE3, 0x38, 0x4F, 0xBE, 0x3D, 0xCF, 0x9F, 0x50, 0x42, 0x95, 0x1C,
0x76, 0x1A, 0x9A, 0x41, 0x08, 0xD9, 0xBA, 0xB9, 0xD6, 0xF6, 0x65, 0x41,
0x22, 0xD4, 0xDF, 0xBD, 0x4E, 0xFD, 0x58, 0xD5, 0x1B, 0x07, 0x14, 0x31,
0xE5, 0xA8, 0xBF, 0x88, 0x22, 0xCF, 0x70, 0x5B, 0x72, 0x9D, 0xC2, 0x6D,
0x87, 0x0F, 0x6F, 0x1B, 0x6C, 0xEF, 0xD7, 0xD1, 0xC0, 0xEE, 0x48, 0xB4,
0xA2, 0xCA, 0xC9, 0x7B, 0xB8, 0xE8, 0xA2, 0x5D, 0x39, 0x35, 0x89, 0xFA,
0xEB, 0x78, 0xCE, 0x51, 0xB1, 0xBA, 0xE6, 0xA4,
])
_KEY_KLQ = bytes.fromhex('E24548EC690E5CAC')
_KEY_KSW = bytes.fromhex('397B4D58C9397B4D58C9')
_KEY_GDATA = bytes.fromhex('A7BF73A09F03D311856F0080ADA96E9B')
_KEY_PANDA = bytes.fromhex('3DD822666516E3B8C5D61871E719E05A')
_KEY_BAIDU = bytes.fromhex('D9A7A3BF85FF4377AD06CFFD1F94E9CC')
_KEY_ZEMANA = b'A8147B3ABF8533AB27FA9551B1FAA385'
_KEY_AMITI = b'AA79e10d15l6o2t8'
_GUID_ASQUARED_LC = b'{A4A1BFF9-301A-40d3-86D3-D1F29E413B28}'
_PHRASE_MB_V1 = b'XBXM8362QIXD9+637HCB02/VN0JF6Z3)cB9UFZMdF3I.*c.,c5SbO7)WNZ8CY1(XMUDb'
_PHRASE_MB_V2 = b'Go9r%8hhAl7Ari;vnQ8wwkmeostfETkzLEf5*+6u8MF.CbsYKbTt9w.cVJbJ+pzyvrsT'
_KEY_MSDEF_PC = bytes([
0x1E, 0x87, 0x78, 0x1B, 0x8D, 0xBA, 0xA8, 0x44, 0xCE, 0x69, 0x70, 0x2C,
0x0C, 0x78, 0xB7, 0x86, 0xA3, 0xF6, 0x23, 0xB7, 0x38, 0xF5, 0xED, 0xF9,
0xAF, 0x83, 0x53, 0x0F, 0xB3, 0xFC, 0x54, 0xFA, 0xA2, 0x1E, 0xB9, 0xCF,
0x13, 0x31, 0xFD, 0x0F, 0x0D, 0xA9, 0x54, 0xF6, 0x87, 0xCB, 0x9E, 0x18,
0x27, 0x96, 0x97, 0x90, 0x0E, 0x53, 0xFB, 0x31, 0x7C, 0x9C, 0xBC, 0xE4,
0x8E, 0x23, 0xD0, 0x53, 0x71, 0xEC, 0xC1, 0x59, 0x51, 0xB8, 0xF3, 0x64,
0x9D, 0x7C, 0xA3, 0x3E, 0xD6, 0x8D, 0xC9, 0x04, 0x7E, 0x82, 0xC9, 0xBA,
0xAD, 0x97, 0x99, 0xD0, 0xD4, 0x58, 0xCB, 0x84, 0x7C, 0xA9, 0xFF, 0xBE,
0x3C, 0x8A, 0x77, 0x52, 0x33, 0x55, 0x7D, 0xDE, 0x13, 0xA8, 0xB1, 0x40,
0x87, 0xCC, 0x1B, 0xC8, 0xF1, 0x0F, 0x6E, 0xCD, 0xD0, 0x83, 0xA9, 0x59,
0xCF, 0xF8, 0x4A, 0x9D, 0x1D, 0x50, 0x75, 0x5E, 0x3E, 0x19, 0x18, 0x18,
0xAF, 0x23, 0xE2, 0x29, 0x35, 0x58, 0x76, 0x6D, 0x2C, 0x07, 0xE2, 0x57,
0x12, 0xB2, 0xCA, 0x0B, 0x53, 0x5E, 0xD8, 0xF6, 0xC5, 0x6C, 0xE7, 0x3D,
0x24, 0xBD, 0xD0, 0x29, 0x17, 0x71, 0x86, 0x1A, 0x54, 0xB4, 0xC2, 0x85,
0xA9, 0xA3, 0xDB, 0x7A, 0xCA, 0x6D, 0x22, 0x4A, 0xEA, 0xCD, 0x62, 0x1D,
0xB9, 0xF2, 0xA2, 0x2E, 0xD1, 0xE9, 0xE1, 0x1D, 0x75, 0xBE, 0xD7, 0xDC,
0x0E, 0xCB, 0x0A, 0x8E, 0x68, 0xA2, 0xFF, 0x12, 0x63, 0x40, 0x8D, 0xC8,
0x08, 0xDF, 0xFD, 0x16, 0x4B, 0x11, 0x67, 0x74, 0xCD, 0x0B, 0x9B, 0x8D,
0x05, 0x41, 0x1E, 0xD6, 0x26, 0x2E, 0x42, 0x9B, 0xA4, 0x95, 0x67, 0x6B,
0x83, 0x98, 0xDB, 0x2F, 0x35, 0xD3, 0xC1, 0xB9, 0xCE, 0xD5, 0x26, 0x36,
0xF2, 0x76, 0x5E, 0x1A, 0x95, 0xCB, 0x7C, 0xA4, 0xC3, 0xDD, 0xAB, 0xDD,
0xBF, 0xF3, 0x82, 0x53,
])
_TABLE_FPROT = bytes([
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0xF2, 0xAC,
0xB4, 0x68, 0xC0, 0x86, 0xB6, 0xE3, 0xF6, 0x45,
0xC8, 0x5D, 0xCF, 0x5E, 0xA2, 0xD6, 0xAE, 0x1A,
0x13, 0x46, 0x5F, 0x3E, 0x99, 0x96, 0x7D, 0x57,
0x7A, 0xF4, 0xDD, 0x34, 0xAF, 0x2A, 0x78, 0x92,
0x9B, 0x35, 0x94, 0x98, 0xA3, 0x76, 0xF1, 0x44,
0xE7, 0xB0, 0xBE, 0x3B, 0x0E, 0x14, 0xC5, 0x79,
0x85, 0xCD, 0xC6, 0xF5, 0xEF, 0x8E, 0x15, 0xD7,
0x77, 0x17, 0x89, 0xF8, 0xCA, 0x82, 0x5A, 0x32,
0xBF, 0x3F, 0xFF, 0x2F, 0x6E, 0x88, 0xA6, 0x12,
0x7B, 0xEC, 0x73, 0xE5, 0x58, 0x66, 0x52, 0x63,
0x5C, 0xAB, 0xEB, 0x49, 0xD3, 0x0F, 0x3C, 0x3A,
0x36, 0xA1, 0x18, 0xED, 0x27, 0x6B, 0xB8, 0x3D,
0xC4, 0x6D, 0x4B, 0x2B, 0x91, 0xDB, 0x4D, 0x8B,
0xA5, 0x83, 0x22, 0x1B, 0xDE, 0x87, 0xFC, 0xFD,
0xBB, 0x8D, 0xE6, 0x7F, 0x6A, 0x26, 0x7C, 0xEE,
0xB5, 0x9F, 0xE4, 0xE9, 0x69, 0x74, 0xC7, 0x56,
0xF9, 0x39, 0x72, 0x23, 0xD8, 0x43, 0x25, 0x1F,
0x4E, 0x61, 0x21, 0x33, 0xAD, 0x31, 0x64, 0xCC,
0x51, 0x9E, 0xFA, 0xF3, 0xD4, 0xBA, 0xD5, 0x6F,
0xF0, 0x7E, 0x1C, 0x29, 0xFB, 0x1D, 0x42, 0xE8,
0x4A, 0x47, 0xAA, 0x90, 0x59, 0x67, 0x65, 0xB2,
0x8A, 0x50, 0xDF, 0x9D, 0x53, 0xA8, 0x19, 0x71,
0x54, 0x93, 0xA0, 0x2D, 0x24, 0x75, 0xE2, 0xFE,
0xBD, 0x97, 0xA9, 0x95, 0xF7, 0x9A, 0xD9, 0x60,
0x10, 0x2C, 0x40, 0x84, 0x2E, 0xC3, 0x41, 0xC1,
0x6C, 0x38, 0x8C, 0xB9, 0x80, 0xDC, 0x1E, 0xCE,
0xC2, 0x8F, 0xA4, 0xC9, 0xE1, 0x9C, 0x30, 0xD2,
0x81, 0x28, 0xB7, 0xA7, 0xDA, 0x70, 0x5B, 0xCB,
0xD1, 0xB1, 0x4F, 0x20, 0x11, 0x37, 0x48, 0xB3,
0xE0, 0x16, 0x62, 0xEA, 0xBC, 0x55, 0x4C, 0xD0,
])
def _is_valid_output(data: bytes | bytearray | memoryview) -> bool:
if len(data) < 2:
return False
from refinery.lib.id import get_structured_data_type
return get_structured_data_type(data) is not None
def _handle_cmc(view: memoryview) -> QuarantineResult | None:
if bytes(view[:23]) != b'CMC Quarantined Malware':
return None
if len(view) < 0x200:
return None
fn_len = _u16(view, 0x50)
filename = bytes(view[0x200:0x200 + fn_len]).rstrip(b'\x00').decode('latin1', errors='replace')
tn_len = _u16(view, 0x6C)
tn_off = 0x200 + fn_len
threat = bytes(view[tn_off:tn_off + tn_len]).rstrip(b'\x00').decode('latin1', errors='replace')
hdr_end = tn_off + tn_len
if len(view) < hdr_end + 4:
return None
buf_len = _u32(view, hdr_end)
payload_raw = bytes(view[hdr_end + 4:hdr_end + 4 + buf_len])
import io
import zipfile
for payload in (_xor_byte(payload_raw, 30), payload_raw):
try:
with zipfile.ZipFile(io.BytesIO(payload)) as zf:
for info in zf.infolist():
if not info.is_dir():
return QuarantineResult(zf.read(info.filename), 'CMC', filename, threat)
except zipfile.BadZipFile:
pass
return None
def _handle_v3b(view: memoryview) -> QuarantineResult | None:
if bytes(view[:16]) != b'AhnLab Inc. 2006':
return None
if len(view) < 0x5C:
return None
payload_off = _u32(view, 0x58) + 0x58
if payload_off >= len(view):
return None
payload = view[payload_off:]
out = _xor_cyclic(payload, _KEY_V3B)
if _is_valid_output(out):
return QuarantineResult(out, 'AhnLab')
raw_key = b'v3backup!@#$%^&)'
out = _xor_cyclic(payload, raw_key)
if _is_valid_output(out):
return QuarantineResult(out, 'AhnLab')
return None
def _handle_avira(view: memoryview) -> QuarantineResult | None:
if bytes(view[:11]) != b'AntiVir Qua':
return None
if len(view) < 20:
return None
payload_off = _u32(view, 16)
if payload_off >= len(view):
return None
return QuarantineResult(_xor_byte(view[payload_off:], 0xAA), 'Avira')
def _handle_avast(view: memoryview) -> QuarantineResult | None:
if bytes(view[:8]) != b'-chest- ':
return None
data = view[8:]
klen = len(_KEY_AVAST)
out = bytearray(len(data))
ki = 0
for i in range(len(data)):
out[i] = data[i] ^ _KEY_AVAST[ki]
ki += 1
if ki >= klen or (i % 0x10000) == 0xFFFF:
ki = 0
return QuarantineResult(out, 'Avast')
def _handle_forticlient(view: memoryview) -> QuarantineResult | None:
if bytes(view[:5]) != b'QUARF':
return None
if len(view) < 0x60:
return None
mal_len = _u32(view, 0x34)
fn_len = _u32(view, 0x58)
tn_len = _u32(view, 0x5C)
fn_off = 0x60
tn_off = fn_off + fn_len
payload_off = tn_off + tn_len
filename = None
threat = None
try:
filename = bytes(view[fn_off:fn_off + fn_len]).decode('utf-16-le').rstrip('\x00')
except Exception:
pass
try:
threat = bytes(view[tn_off:tn_off + tn_len]).decode('utf-16-le').rstrip('\x00')
except Exception:
pass
if payload_off + mal_len > len(view):
mal_len = len(view) - payload_off
if mal_len <= 0:
return None
return QuarantineResult(
_xor_byte(view[payload_off:payload_off + mal_len], 0xAB),
'FortiClient', filename, threat,
)
def _handle_klq(view: memoryview) -> QuarantineResult | None:
if bytes(view[:4]) != b'KLQB':
return None
if len(view) < 0x34:
return None
header_len = _u32(view, 0x08)
orig_len = _u32(view, 0x30)
if header_len + orig_len > len(view):
return None
payload = view[header_len:header_len + orig_len]
out = _xor_cyclic(payload, _KEY_KLQ)
filename = None
meta_off = _u32(view, 0x10)
meta_len = _u32(view, 0x20)
if meta_off + meta_len <= len(view):
try:
filename = _parse_klq_metadata(view, meta_off, meta_len)
except Exception:
pass
return QuarantineResult(out, 'Kaspersky', filename)
def _parse_klq_metadata(
view: memoryview,
meta_off: int,
meta_len: int,
) -> str | None:
pos = meta_off
end = meta_off + meta_len
filename = None
while pos + 4 < end:
chunk_len = _u32(view, pos)
if chunk_len == 0:
break
pos += 4
if pos + chunk_len > end:
break
chunk = _xor_cyclic(view[pos:pos + chunk_len], _KEY_KLQ)
if len(chunk) >= 4:
id_len = _u32(chunk, 0)
if 4 + id_len <= len(chunk):
id_name = bytes(chunk[4:4 + id_len]).rstrip(b'\x00')
id_val = chunk[4 + id_len:]
if id_name == b'cNP_QB_FULLNAME' and id_val:
try:
filename = bytes(id_val).decode('utf-16-le').rstrip('\x00')
except Exception:
filename = bytes(id_val).replace(
b'\x00', b'').decode('latin1', errors='replace')
pos += chunk_len
return filename
def _vsbx_crc32_decrypt(payload: bytearray, base_key: int, data_off_raw: int) -> bytearray:
unaligned = data_off_raw % 4
off = data_off_raw - unaligned
i = 0
while i < len(payload):
keyval = (base_key + off) & 0xFFFFFFFF
crc_bytes = struct.pack('<I', zlib.crc32(struct.pack('<I', keyval)) & 0xFFFFFFFF)
start = unaligned
unaligned = 0
for j in range(start, 4):
if i >= len(payload):
break
payload[i] ^= crc_bytes[j]
i += 1
off += 4
return payload
def _handle_vsbx(view: memoryview) -> QuarantineResult | None:
if len(view) < 10:
return None
d32 = int.from_bytes(bytes(view[:4]), 'big')
if d32 != 0xA9ACBDA7:
return None
decoded = _xor_byte(view, 0xFF)
if bytes(decoded[:4]) != b'VSBX':
return None
data_off_raw = _u32(decoded, 4) + 10
num_tags = _u16(decoded, 8)
if num_tags > 15:
return None
base_key = 0
enc_method = 0
pos = 10
for _ in range(num_tags):
if pos + 3 > len(decoded):
break
code = decoded[pos]
tag_len = _u16(decoded, pos + 1)
pos += 3
if pos + tag_len > len(decoded):
break
tag_data = decoded[pos:pos + tag_len]
if code == 6 and tag_len >= 4:
base_key = _u32(tag_data, 0)
elif code == 7 and tag_len >= 4:
enc_method = _u32(tag_data, 0)
pos += tag_len
if data_off_raw >= len(decoded):
return None
payload = bytearray(decoded[data_off_raw:])
if enc_method == 2:
_vsbx_crc32_decrypt(payload, base_key, data_off_raw)
return QuarantineResult(bytes(payload), 'TrendMicro')
def _handle_gdata(view: memoryview) -> QuarantineResult | None:
if len(view) < 16:
return None
if _u32(view, 0) != 0xCAFEBABE:
return None
hdr_len = _u32(view, 4)
body_start = 8 + hdr_len
if body_start + 8 > len(view):
return None
if _u32(view, body_start) != 0xBAADF00D:
return None
body_len = _u32(view, body_start + 4)
payload_start = body_start + 8 + body_len
if payload_start >= len(view):
return None
return QuarantineResult(_rc4(_KEY_GDATA, view[payload_start:]), 'G-Data')
def _handle_msdef_pc(view: memoryview) -> QuarantineResult | None:
if len(view) < 0x3C:
return None
d16 = _u16(view, 0)
if d16 == 0x0BAD:
decrypted = _rc4(_KEY_MSDEF_PC, view)
header_extra = _u32(decrypted, 8)
payload_off = 0x28 + header_extra
if payload_off >= len(decrypted):
return None
return QuarantineResult(bytes(decrypted[payload_off:]), 'Microsoft Defender')
if d16 == 0xD345:
header = bytearray(_rc4(_KEY_MSDEF_PC, view[:0x3C]))
if _u32(header, 0) != 0x01C5E8DB:
return None
len1 = _u32(header, 0x28)
len2 = _u32(header, 0x2C)
dec1 = _rc4(_KEY_MSDEF_PC, view[0x3C:0x3C + len1])
dec2 = _rc4(_KEY_MSDEF_PC, view[0x3C + len1:0x3C + len1 + len2])
return QuarantineResult(bytes(header) + bytes(dec1) + bytes(dec2), 'Microsoft Defender')
return None
def _handle_fprot(view: memoryview) -> QuarantineResult | None:
if bytes(view[:3]) != b'KSS':
return None
if len(view) < 8:
return None
data_off = _u32(view, 4) + 0xDC
if data_off >= len(view):
return None
payload = view[data_off:]
out = bytearray(len(payload))
for i in range(len(payload)):
out[i] = _TABLE_FPROT[payload[i]]
return QuarantineResult(out, 'F-Prot')
def _handle_mcafee_bup(view: memoryview) -> QuarantineResult | None:
if bytes(view[:8]) != b'\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1':
return None
from refinery.lib.ole.file import OleFile
try:
with OleFile(view) as ole:
for path in ole.listdir():
joined = '/'.join(path)
stream = ole.openstream(joined)
content = _xor_byte(stream.read(), 0x6A)
if _is_valid_output(content):
return QuarantineResult(content, 'McAfee')
except Exception:
pass
return None
# --- BLIND HANDLERS ---
def _handle_bitdefender(view: memoryview) -> QuarantineResult | None:
if len(view) < 16:
return None
out = bytearray(len(view))
cl = 25
dl = 43
for i in range(len(view)):
out[i] = ((view[i] - dl) & 0xFF) ^ cl
cl = (cl + 3) & 0xFF
dl = (dl + 20) & 0xFF
return QuarantineResult(out, 'BitDefender')
def _handle_eset(view: memoryview) -> QuarantineResult | None:
if len(view) < 16:
return None
out = bytearray(len(view))
for i in range(len(view)):
out[i] = ((view[i] - 84) & 0xFF) ^ 0xA5
return QuarantineResult(out, 'ESET')
def _handle_k7(view: memoryview) -> QuarantineResult | None:
if len(view) < 0x17C:
return None
payload_len = _u32(view, 0x128)
payload_off = 0x178
if payload_off + payload_len > len(view):
payload_len = len(view) - payload_off
if payload_len <= 0:
return None
return QuarantineResult(_xor_byte(view[payload_off:payload_off + payload_len], 0xFF), 'K7')
def _handle_malwarebytes(view: memoryview) -> QuarantineResult | None:
if len(view) < 16:
return None
for phrase in (_PHRASE_MB_V1, _PHRASE_MB_V2):
key = _md5(phrase)
out = _rc4(key, view)
if _is_valid_output(out):
return QuarantineResult(out, 'MalwareBytes')
return None
def _handle_symantec_vbn(view: memoryview) -> QuarantineResult | None:
if len(view) < 0x12B8 + 16:
return None
data_off = _u32(view, 0)
if data_off != 0x1290:
return None
decrypted = _xor_byte(view, 0x5A)
offset = data_off + 0x28
xor_next = False
has_header = True
for _ in range(20000):
if offset + 1 >= len(decrypted):
break
code = decrypted[offset]
offset += 1
if code in (1, 10):
tag_len = 2
offset += tag_len
elif code in (3, 6):
if offset + 4 > len(decrypted):
break
tag_len = 5
offset += tag_len
elif code == 4:
if offset + 8 > len(decrypted):
break
codeval = _u64(decrypted, offset)
offset += 8
if xor_next:
has_header = False
continue
else:
if offset + 4 > len(decrypted):
break
codeval = _u32(decrypted, offset)
offset += 4
if code == 9:
if codeval == 0x08:
xor_next = True
offset += codeval
continue
elif codeval == 0x10:
xor_next = False
offset += codeval
continue
if xor_next and offset + codeval <= len(decrypted):
container = _xor_byte(decrypted[offset:offset + codeval], 0xFF)
if has_header and len(container) > 12:
hdr_len = _u32(container, 8)
if hdr_len < len(container):
payload = container[hdr_len:]
has_header = False
return QuarantineResult(bytes(payload), 'Symantec')
elif not has_header:
return QuarantineResult(bytes(container), 'Symantec')
offset += codeval
return None
def _handle_symantec_qfm(view: memoryview) -> QuarantineResult | None:
if len(view) < 0x30:
return None
qfm_offset = _u32(view, 0)
if qfm_offset == 0 or qfm_offset >= len(view):
return None
if view[qfm_offset] != 0x5A:
return None
decrypted = _xor_byte(view[qfm_offset:], 0x5A)
if len(decrypted) < 0x20:
return None
total_size = _u64(decrypted, 0x18)
struct1_offset = total_size
if struct1_offset + 0x5A >= len(decrypted):
return None
s1 = decrypted[struct1_offset:]
if len(s1) < 12 or s1[0] != 0x03 or s1[1] != 0x03:
return None
sha1_wide_size = _u32(s1, 8)
if sha1_wide_size != 0x52:
return None
s1_size = 12 + sha1_wide_size
s2_start = struct1_offset + s1_size
if s2_start + 23 > len(decrypted):
return None
s2 = decrypted[s2_start:]
original_file_size = _u64(s2, 15)
s2_size = 23
part3_start = s2_start + s2_size
if part3_start >= len(decrypted):
return None
part3_byte = decrypted[part3_start]
if part3_byte == 8:
if part3_start + 5 >= len(decrypted):
return None
sd_size = _u32(decrypted, part3_start + 1)
chunk_start = part3_start + 1 + 4 + sd_size + 5 + 1 + 8
elif part3_byte == 9:
chunk_start = part3_start
else:
return None
if chunk_start >= len(decrypted):
return None
pos = chunk_start
plain = bytearray()
while len(plain) < original_file_size:
if pos >= len(decrypted):
break
if decrypted[pos] != 9:
break
pos += 1
if pos + 4 > len(decrypted):
break
size = _u32(decrypted, pos)
pos += 4
if pos + size > len(decrypted):
break
chunk = _xor_byte(decrypted[pos:pos + size], 0xFF)
plain.extend(chunk)
pos += size
if not plain:
return None
return QuarantineResult(bytes(plain[:original_file_size]), 'Symantec')
def _handle_symantec_cc(view: memoryview) -> QuarantineResult | None:
if len(view) < 33:
return None
key = bytes(view[16:32])
payload = view[32:]
out = _blowfish_ecb_swap(key, payload)
return QuarantineResult(out, 'Symantec')
def _handle_symantec_qbd(view: memoryview) -> QuarantineResult | None:
if len(view) < 16:
return None
return QuarantineResult(_xor_byte(view, 0xB3), 'Symantec')
def _handle_panda(view: memoryview) -> QuarantineResult | None:
if len(view) < 4:
return None
if bytes(view[:2]) != b'PK':
return None
import io
import zipfile
try:
with zipfile.ZipFile(io.BytesIO(bytes(view))) as zf:
for info in zf.infolist():
if info.is_dir():
continue
raw = zf.read(info.filename)
dec = _blowfish_ecb(_KEY_PANDA, raw)
try:
out = bytearray(zlib.decompress(dec, 16 + zlib.MAX_WBITS))
except zlib.error:
try:
out = bytearray(zlib.decompress(dec))
except zlib.error:
continue
if _is_valid_output(out):
return QuarantineResult(out, 'Panda')
except zipfile.BadZipFile:
pass
return None
def _handle_baidu(view: memoryview) -> QuarantineResult | None:
if len(view) < 0x58:
return None
pos = 0x52
try:
for _ in range(7):
if pos + 4 > len(view):
return None
field_len = _u32(view, pos)
pos += 4 + field_len
if pos + 4 > len(view):
return None
pos += 4
except Exception:
return None
out = bytearray()
while pos + 2 <= len(view):
chunk_len = _u16(view, pos)
pos += 2
if chunk_len == 0 or pos + chunk_len > len(view):
break
try:
decompressed = bytearray(zlib.decompress(bytes(view[pos:pos + chunk_len])))
except zlib.error:
return None
b = decompressed[0]
for i in range(len(decompressed)):
b ^= _KEY_BAIDU[i % 16]
decompressed[0] = b
out.extend(decompressed)
pos += chunk_len
if not out:
return None
return QuarantineResult(out, 'Baidu')
def _handle_amiti(view: memoryview) -> QuarantineResult | None:
if len(view) < 16:
return None
key = bytes(b ^ 0xA4 for b in _KEY_AMITI)
return QuarantineResult(_rc4(key, view), 'Amiti')
def _handle_asquared(view: memoryview) -> QuarantineResult | None:
if len(view) < 0x42:
return None
data_start = 0x1A
payload_off_field = _u32(view, data_start + 0x24)
payload_off = data_start + payload_off_field
if payload_off >= len(view):
payload_off = data_start
key = _md5(_GUID_ASQUARED_LC.decode('ascii').encode('utf-16-le'))
return QuarantineResult(_rc4(key, view[payload_off:]), 'ASquared')
def _handle_zemana(view: memoryview) -> QuarantineResult | None:
if len(view) < 16:
return None
return QuarantineResult(_rc4(_KEY_ZEMANA, view), 'Zemana')
def _handle_kserver(view: memoryview) -> QuarantineResult | None:
if len(view) < 16:
return None
if _u16(view, 0) != 0xAF1F:
return None
return QuarantineResult(_xor_cyclic(view, _KEY_KLQ), 'Kaspersky Server')
def _handle_ksw(view: memoryview) -> QuarantineResult | None:
if len(view) < 16:
return None
return QuarantineResult(_xor_cyclic(view, _KEY_KSW), 'Kaspersky')
def _handle_quickheal(view: memoryview) -> QuarantineResult | None:
if len(view) < 16:
return None
out = bytearray(len(view))
for i in range(len(view)):
b = view[i]
out[i] = ((b >> 4) | (b << 4)) & 0xFF
return QuarantineResult(out, 'QuickHeal')
def _handle_cisco_amp(view: memoryview) -> QuarantineResult | None:
if len(view) < 16:
return None
return QuarantineResult(_xor_byte(view, 0x77), 'Cisco AMP')
def _handle_sentinelone(view: memoryview) -> QuarantineResult | None:
if len(view) < 16:
return None
return QuarantineResult(_xor_byte(view, 0xFF), 'SentinelOne')
def _handle_ms_antimalware(view: memoryview) -> QuarantineResult | None:
if len(view) < 16:
return None
return QuarantineResult(_xor_byte(view, 0xFF), 'MS Antimalware')
def _handle_ms_def_mac(view: memoryview) -> QuarantineResult | None:
if len(view) < 4:
return None
return QuarantineResult(_xor_byte(view, 0x25), 'MS Defender Mac')
def _handle_superantispyware(view: memoryview) -> QuarantineResult | None:
if len(view) < 16:
return None
return QuarantineResult(_xor_byte(view, 0xED), 'SUPERAntiSpyware')
def _handle_vipre(view: memoryview) -> QuarantineResult | None:
if len(view) < 16:
return None
return QuarantineResult(_xor_byte(view, 0x33), 'Vipre')
def _handle_bullguard(view: memoryview) -> QuarantineResult | None:
if len(view) < 16:
return None
out = bytearray(view)
for i in range(0, len(out), 2):
out[i] ^= 0x3F
return QuarantineResult(out, 'BullGuard')
def _handle_esafe(view: memoryview) -> QuarantineResult | None:
if len(view) < 4:
return None
import base64
try:
out = base64.b64decode(bytes(view))
except Exception:
return None
return QuarantineResult(bytearray(out), 'eSafe')
def _handle_lumension(view: memoryview) -> QuarantineResult | None:
if len(view) < 36:
return None
try:
out = zlib.decompress(bytes(view[32:]), 16 + zlib.MAX_WBITS)
except zlib.error:
try:
out = zlib.decompress(bytes(view[32:]))
except zlib.error:
return None
return QuarantineResult(bytearray(out), 'Lumension')
def _handle_totalav(view: memoryview) -> QuarantineResult | None:
if bytes(view[:2]) != b'PK':
return None
import io
import zipfile
try:
with zipfile.ZipFile(io.BytesIO(bytes(view))) as zf:
for info in zf.infolist():
if info.is_dir():
continue
try:
data = zf.read(info.filename, pwd=b'infected')
except (RuntimeError, zipfile.BadZipFile):
continue
return QuarantineResult(bytearray(data), 'TotalAV', info.filename)
except zipfile.BadZipFile:
pass
return None
def _handle_spybot(view: memoryview) -> QuarantineResult | None:
if bytes(view[:2]) != b'PK':
return None
import io
import zipfile
try:
with zipfile.ZipFile(io.BytesIO(bytes(view))) as zf:
for info in zf.infolist():
if info.is_dir():
continue
try:
data = zf.read(info.filename, pwd=b'recovery')
except (RuntimeError, zipfile.BadZipFile):
continue
return QuarantineResult(bytearray(data), 'Spybot', info.filename)
except zipfile.BadZipFile:
pass
return None
_MAGIC_HANDLERS = [
_handle_cmc,
_handle_v3b,
_handle_avira,
_handle_avast,
_handle_forticlient,
_handle_klq,
_handle_vsbx,
_handle_gdata,
_handle_msdef_pc,
_handle_fprot,
_handle_mcafee_bup,
]
_BLIND_HANDLERS = [
_handle_kserver,
_handle_ms_def_mac,
_handle_symantec_vbn,
_handle_symantec_qfm,
_handle_k7,
_handle_totalav,
_handle_spybot,
_handle_panda,
_handle_malwarebytes,
_handle_symantec_cc,
_handle_bitdefender,
_handle_eset,
_handle_baidu,
_handle_amiti,
_handle_asquared,
_handle_zemana,
_handle_symantec_qbd,
_handle_quickheal,
_handle_cisco_amp,
_handle_sentinelone,
_handle_ms_antimalware,
_handle_superantispyware,
_handle_vipre,
_handle_bullguard,
_handle_esafe,
_handle_lumension,
_handle_ksw,
]
class Vendor(str, enum.Enum):
AhnLab = 'ahnlab' # noqa
Amiti = 'amiti' # noqa
ASquared = 'asquared' # noqa
Avast = 'avast' # noqa
Avira = 'avira' # noqa
Baidu = 'baidu' # noqa
BitDefender = 'bitdefender' # noqa
BullGuard = 'bullguard' # noqa
CiscoAMP = 'ciscoamp' # noqa
CMC = 'cmc' # noqa
ESafe = 'esafe' # noqa
ESET = 'eset' # noqa
FortiClient = 'forticlient' # noqa
FProt = 'fprot' # noqa
GData = 'gdata' # noqa
K7 = 'k7' # noqa
Kaspersky = 'kaspersky' # noqa
KasperskyServer = 'kserver' # noqa
KasperskySW = 'ksw' # noqa
Lumension = 'lumension' # noqa
MalwareBytes = 'malwarebytes' # noqa
McAfee = 'mcafee' # noqa
MSDefender = 'msdefender' # noqa
MSDefenderMac = 'msdefmac' # noqa
MSAntimalware = 'msamalware' # noqa
Panda = 'panda' # noqa
QuickHeal = 'quickheal' # noqa
SentinelOne = 'sentinelone' # noqa
Spybot = 'spybot' # noqa
SUPERAntiSpyware = 'superantispyware' # noqa
SymantecVBN = 'symvbn' # noqa
SymantecCC = 'symcc' # noqa
SymantecQBD = 'symqbd' # noqa
SymantecQFM = 'symqfm' # noqa
TotalAV = 'totalav' # noqa
TrendMicro = 'trendmicro' # noqa
Vipre = 'vipre' # noqa
Zemana = 'zemana' # noqa
_VENDOR_TO_HANDLER = {
Vendor.AhnLab : _handle_v3b,
Vendor.Amiti : _handle_amiti,
Vendor.ASquared : _handle_asquared,
Vendor.Avast : _handle_avast,
Vendor.Avira : _handle_avira,
Vendor.Baidu : _handle_baidu,
Vendor.BitDefender : _handle_bitdefender,
Vendor.BullGuard : _handle_bullguard,
Vendor.CiscoAMP : _handle_cisco_amp,
Vendor.CMC : _handle_cmc,
Vendor.ESafe : _handle_esafe,
Vendor.ESET : _handle_eset,
Vendor.FortiClient : _handle_forticlient,
Vendor.FProt : _handle_fprot,
Vendor.GData : _handle_gdata,
Vendor.K7 : _handle_k7,
Vendor.Kaspersky : _handle_klq,
Vendor.KasperskyServer : _handle_kserver,
Vendor.KasperskySW : _handle_ksw,
Vendor.Lumension : _handle_lumension,
Vendor.MalwareBytes : _handle_malwarebytes,
Vendor.McAfee : _handle_mcafee_bup,
Vendor.MSDefender : _handle_msdef_pc,
Vendor.MSDefenderMac : _handle_ms_def_mac,
Vendor.MSAntimalware : _handle_ms_antimalware,
Vendor.Panda : _handle_panda,
Vendor.QuickHeal : _handle_quickheal,
Vendor.SentinelOne : _handle_sentinelone,
Vendor.Spybot : _handle_spybot,
Vendor.SUPERAntiSpyware : _handle_superantispyware,
Vendor.SymantecVBN : _handle_symantec_vbn,
Vendor.SymantecCC : _handle_symantec_cc,
Vendor.SymantecQBD : _handle_symantec_qbd,
Vendor.SymantecQFM : _handle_symantec_qfm,
Vendor.TotalAV : _handle_totalav,
Vendor.TrendMicro : _handle_vsbx,
Vendor.Vipre : _handle_vipre,
Vendor.Zemana : _handle_zemana,
}
def unquarantine(
data: bytes | bytearray | memoryview,
vendor: Vendor | None = None,
) -> QuarantineResult:
"""
Extract the original file from an antivirus quarantine container. If `vendor` is specified,
only the handler for that vendor is tried. Otherwise, handlers with known magic are tried
first, followed by blind handlers with output validation.
"""
view = memoryview(bytearray(data))
if vendor is not None:
handler = _VENDOR_TO_HANDLER.get(vendor)
if handler is None:
raise ValueError(F'unknown quarantine vendor: {vendor}')
result = handler(view)
if result is not None:
return result
raise ValueError(
F'the specified vendor format ({vendor}) could not decode this data')
for handler in _MAGIC_HANDLERS:
result = handler(view)
if result is not None:
return result
for handler in _BLIND_HANDLERS:
try:
result = handler(view)
except Exception:
continue
if result is not None and _is_valid_output(result.data):
return result
raise ValueError('no quarantine format matched this data')
Functions
def unquarantine(data, vendor=None)-
Extract the original file from an antivirus quarantine container. If
vendoris specified, only the handler for that vendor is tried. Otherwise, handlers with known magic are tried first, followed by blind handlers with output validation.Expand source code Browse git
def unquarantine( data: bytes | bytearray | memoryview, vendor: Vendor | None = None, ) -> QuarantineResult: """ Extract the original file from an antivirus quarantine container. If `vendor` is specified, only the handler for that vendor is tried. Otherwise, handlers with known magic are tried first, followed by blind handlers with output validation. """ view = memoryview(bytearray(data)) if vendor is not None: handler = _VENDOR_TO_HANDLER.get(vendor) if handler is None: raise ValueError(F'unknown quarantine vendor: {vendor}') result = handler(view) if result is not None: return result raise ValueError( F'the specified vendor format ({vendor}) could not decode this data') for handler in _MAGIC_HANDLERS: result = handler(view) if result is not None: return result for handler in _BLIND_HANDLERS: try: result = handler(view) except Exception: continue if result is not None and _is_valid_output(result.data): return result raise ValueError('no quarantine format matched this data')
Classes
class QuarantineResult (data, vendor, filename=None, threat=None)-
QuarantineResult(data, vendor, filename, threat)
Expand source code Browse git
class QuarantineResult(NamedTuple): data: bytes | bytearray vendor: str filename: str | None = None threat: str | None = NoneAncestors
- builtins.tuple
Instance variables
var data-
Alias for field number 0
Expand source code Browse git
class QuarantineResult(NamedTuple): data: bytes | bytearray vendor: str filename: str | None = None threat: str | None = None var vendor-
Alias for field number 1
Expand source code Browse git
class QuarantineResult(NamedTuple): data: bytes | bytearray vendor: str filename: str | None = None threat: str | None = None var filename-
Alias for field number 2
Expand source code Browse git
class QuarantineResult(NamedTuple): data: bytes | bytearray vendor: str filename: str | None = None threat: str | None = None var threat-
Alias for field number 3
Expand source code Browse git
class QuarantineResult(NamedTuple): data: bytes | bytearray vendor: str filename: str | None = None threat: str | None = None
class Vendor (*args, **kwds)-
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.str() (if defined) or repr(object). encoding defaults to 'utf-8'. errors defaults to 'strict'.
Expand source code Browse git
class Vendor(str, enum.Enum): AhnLab = 'ahnlab' # noqa Amiti = 'amiti' # noqa ASquared = 'asquared' # noqa Avast = 'avast' # noqa Avira = 'avira' # noqa Baidu = 'baidu' # noqa BitDefender = 'bitdefender' # noqa BullGuard = 'bullguard' # noqa CiscoAMP = 'ciscoamp' # noqa CMC = 'cmc' # noqa ESafe = 'esafe' # noqa ESET = 'eset' # noqa FortiClient = 'forticlient' # noqa FProt = 'fprot' # noqa GData = 'gdata' # noqa K7 = 'k7' # noqa Kaspersky = 'kaspersky' # noqa KasperskyServer = 'kserver' # noqa KasperskySW = 'ksw' # noqa Lumension = 'lumension' # noqa MalwareBytes = 'malwarebytes' # noqa McAfee = 'mcafee' # noqa MSDefender = 'msdefender' # noqa MSDefenderMac = 'msdefmac' # noqa MSAntimalware = 'msamalware' # noqa Panda = 'panda' # noqa QuickHeal = 'quickheal' # noqa SentinelOne = 'sentinelone' # noqa Spybot = 'spybot' # noqa SUPERAntiSpyware = 'superantispyware' # noqa SymantecVBN = 'symvbn' # noqa SymantecCC = 'symcc' # noqa SymantecQBD = 'symqbd' # noqa SymantecQFM = 'symqfm' # noqa TotalAV = 'totalav' # noqa TrendMicro = 'trendmicro' # noqa Vipre = 'vipre' # noqa Zemana = 'zemana' # noqaAncestors
- builtins.str
- enum.Enum
Class variables
var AhnLab-
The type of the None singleton.
var Amiti-
The type of the None singleton.
var ASquared-
The type of the None singleton.
var Avast-
The type of the None singleton.
var Avira-
The type of the None singleton.
var Baidu-
The type of the None singleton.
var BitDefender-
The type of the None singleton.
var BullGuard-
The type of the None singleton.
var CiscoAMP-
The type of the None singleton.
var CMC-
The type of the None singleton.
var ESafe-
The type of the None singleton.
var ESET-
The type of the None singleton.
var FortiClient-
The type of the None singleton.
var FProt-
The type of the None singleton.
var GData-
The type of the None singleton.
var K7-
The type of the None singleton.
var Kaspersky-
The type of the None singleton.
var KasperskyServer-
The type of the None singleton.
var KasperskySW-
The type of the None singleton.
var Lumension-
The type of the None singleton.
var MalwareBytes-
The type of the None singleton.
var McAfee-
The type of the None singleton.
var MSDefender-
The type of the None singleton.
var MSDefenderMac-
The type of the None singleton.
var MSAntimalware-
The type of the None singleton.
var Panda-
The type of the None singleton.
var QuickHeal-
The type of the None singleton.
var SentinelOne-
The type of the None singleton.
var Spybot-
The type of the None singleton.
var SUPERAntiSpyware-
The type of the None singleton.
var SymantecVBN-
The type of the None singleton.
var SymantecCC-
The type of the None singleton.
var SymantecQBD-
The type of the None singleton.
var SymantecQFM-
The type of the None singleton.
var TotalAV-
The type of the None singleton.
var TrendMicro-
The type of the None singleton.
var Vipre-
The type of the None singleton.
var Zemana-
The type of the None singleton.