From 17c138c8458fcf155a55197f4442dd2939a85817 Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Mon, 31 Mar 2025 10:06:10 +0200 Subject: [PATCH 01/40] Add initial commit From 46c19ab5e95e319955349d16490f96e9c0181ce9 Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Wed, 2 Apr 2025 10:29:13 +0200 Subject: [PATCH 02/40] Fix operating system type Operating system was not able to equal causing NotImplementedError --- maldump/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maldump/utils.py b/maldump/utils.py index c7e8f64..4304ceb 100755 --- a/maldump/utils.py +++ b/maldump/utils.py @@ -29,7 +29,7 @@ def decode(self, plaintext: bytes) -> bytes: class RawTimeConverter: def __init__(self, time_type: str): - self.time_type = time_type + self.time_type = OperatingSystem(time_type) def _decode_windows(self, wintime_bytes: bytes) -> datetime: wintime = int.from_bytes(wintime_bytes, byteorder="little") From 56589c3ead36a880af34d2a3ff53621e54ed3071 Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Mon, 7 Apr 2025 13:38:36 +0200 Subject: [PATCH 03/40] Add logging possibility using arguments Introducing a new argument `--log-level` or `-t` (for traceback) which sets the verbosity level of logging --- maldump/__main__.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/maldump/__main__.py b/maldump/__main__.py index 7c18300..11a2dc7 100755 --- a/maldump/__main__.py +++ b/maldump/__main__.py @@ -156,6 +156,13 @@ def parse_cli() -> argparse.Namespace: parser.add_argument( "-a", "--all", action="store_true", help="equivalent of running both -q and -m" ) + parser.add_argument( + "-t", + "--log-level", + choices=["critical", "fatal", "error", "warn", "warning", "info", "debug"], + default="warning", + help="log level", + ) parser.add_argument( "-v", "--version", action="version", version="%(prog)s " + __version__ ) From 84f8ca0e817d4c87840819b54db474e084792d0d Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Mon, 7 Apr 2025 13:39:19 +0200 Subject: [PATCH 04/40] Add logging initializer --- maldump/__main__.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/maldump/__main__.py b/maldump/__main__.py index 11a2dc7..f8eccc6 100755 --- a/maldump/__main__.py +++ b/maldump/__main__.py @@ -6,6 +6,7 @@ import csv import ctypes import io +import logging import os import sys import tarfile @@ -25,6 +26,7 @@ def main() -> None: init() args = parse_cli() + init_logging(args.log_level) # Admin privileges are required for optimal function (windows only) if sys.platform == "win32" and not ctypes.windll.shell32.IsUserAnAdmin(): @@ -177,5 +179,22 @@ def parse_cli() -> argparse.Namespace: return parser.parse_args() +def init_logging(log_level: str): + numeric_level = getattr(logging, log_level.upper(), None) + if not isinstance(numeric_level, int): + raise ValueError(f"Invalid log level: {log_level}") + + logging.basicConfig( + handlers=[ + # logging.FileHandler("syslog.log", mode="w", encoding="utf-8"), + logging.StreamHandler(sys.stderr) + ], + level=numeric_level, + format="%(asctime)s:%(levelname)s:%(name)s:%(module)s:%(message)s", + ) + logging.debug("Logging started, logger initialized successfully") + logging.info("Logging as user %s", getpass.getuser()) + + if __name__ == "__main__": main() From f68511ae2fc01ac0b88fbfd4d37a6c3afead55ca Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Mon, 7 Apr 2025 13:39:38 +0200 Subject: [PATCH 05/40] Add logging in __main__.py --- maldump/__main__.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/maldump/__main__.py b/maldump/__main__.py index f8eccc6..cb66a74 100755 --- a/maldump/__main__.py +++ b/maldump/__main__.py @@ -5,6 +5,7 @@ import argparse import csv import ctypes +import getpass import io import logging import os @@ -30,6 +31,9 @@ def main() -> None: # Admin privileges are required for optimal function (windows only) if sys.platform == "win32" and not ctypes.windll.shell32.IsUserAnAdmin(): + logging.critical( + "The program tried to be executed on Windows machine without proper privileges" + ) print("Please try again with admin privileges") sys.exit(1) @@ -39,9 +43,15 @@ def main() -> None: # Switch to root partition os.chdir(args.root_dir) + logging.debug( + 'Working in directory "%s", files would be stored into "%s"', os.getcwd(), dest + ) + # Get a list of all installed avs avs = AVManager.detect() + logging.debug("Detected AVs: %s", [av.name for av in avs]) + if args.quar: export_files(avs, dest) elif args.meta: From ccdc34fa88bd8e0afb2c7a4c10c7179dfd6a59c0 Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Mon, 7 Apr 2025 13:39:50 +0200 Subject: [PATCH 06/40] Add logging in utils.py --- maldump/utils.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/maldump/utils.py b/maldump/utils.py index 4304ceb..e7ef456 100755 --- a/maldump/utils.py +++ b/maldump/utils.py @@ -3,6 +3,7 @@ """ import contextlib +import logging from datetime import datetime, timezone from arc4 import ARC4 @@ -55,8 +56,11 @@ class DatetimeConverter: @staticmethod # type: ignore def get_dt_from_stat(stat) -> datetime: + logging.debug("Getting datetime from stat") ctime = stat.st_ctime_ns with contextlib.suppress(AttributeError): + logging.debug("Trying to extract birthtime") ctime = stat.st_birthtime_ns + logging.debug("Birthtime extracted successfully") return datetime.fromtimestamp(ctime // 1000000000) From fde06b8101e904c1741cde49c33c5222b130f53c Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Mon, 7 Apr 2025 13:42:50 +0200 Subject: [PATCH 07/40] Add logging and error handling in eset_parser.py The error handling process tries to get rid of maldump failing to execute. This is caused by throwing exceptions in Python on incorrect operations. Now, logging every step and caught exception alongside with continuing in the program execution --- maldump/parsers/eset_parser.py | 88 +++++++++++++++++++++++++++------- 1 file changed, 70 insertions(+), 18 deletions(-) diff --git a/maldump/parsers/eset_parser.py b/maldump/parsers/eset_parser.py index 3b21433..b35b584 100644 --- a/maldump/parsers/eset_parser.py +++ b/maldump/parsers/eset_parser.py @@ -16,12 +16,15 @@ from __future__ import annotations import binascii +import logging import re import struct import sys from datetime import datetime, timezone from pathlib import Path +from kaitaistruct import KaitaiStructError + from maldump.constants import ThreatMetadata from maldump.parsers.kaitai.eset_ndf_parser import EsetNdfParser as KaitaiParserMetadata from maldump.structures import Parser, QuarEntry @@ -57,25 +60,22 @@ _hashTypeHeaders = {"ObjectHash": OBJECTHASH_HEADER, "ProgHash": PROGHASH_HEADER} -def eprint(*args, **kwargs): - """Prints debug messages to stderr""" - print(*args, file=sys.stderr, **kwargs) - - def _infoNotFound(field): - eprint("Eset Info: field not found: " + field) + logging.info("Parsing data in ESET led to field not found: %s", field) def _warningUnexpected(field): - eprint("Eset Warning: unexpected bytes in field " + field) + logging.warning("Parsing data in ESET found unexpected bytes in field %s", field) def _winToUnixTimestamp(winTimestamp): + logging.debug("Converting Windows to Unix time") magicNumber = 11644473600 return (winTimestamp / 10000000) - magicNumber def _extractDataType(dataType, rawRecord): + logging.debug("Extracting data, type: %s", dataType) # Format: dataType_HEADER + '??' + NULL + objectData + NULL dataType_HEADER = _dataTypeHeaders[dataType] @@ -93,6 +93,7 @@ def _extractDataType(dataType, rawRecord): def _extractHashType(hashType, rawRecord): + logging.debug("Extracting hash, type %s", hashType) # Format: hashType_HEADER + '??' + NULL + hashData[20] hashType_HEADER = _hashTypeHeaders[hashType] @@ -109,6 +110,7 @@ def _extractHashType(hashType, rawRecord): def _extractFirstSeen(rawRecord): + logging.debug("Extracting first seen") # Format: FIRSTSEEN_HEADER + UnixTimestamp[4] offset = rawRecord.find(FIRSTSEEN_HEADER) @@ -121,6 +123,7 @@ def _extractFirstSeen(rawRecord): def _extractTimestamp(rawRecord): + logging.debug("Extracting timestamp") # Format: RECORD_HEADER + ID[4] + MicrosoftTimestamp[8] littleEndianTimestamp = rawRecord[4:12] @@ -130,6 +133,7 @@ def _extractTimestamp(rawRecord): def _checkID(recordId, rawRecord): + logging.debug("Checking record ID") littleEndianIds = [rawRecord[0:4], rawRecord[16:20]] for littleEndianId in littleEndianIds: if struct.unpack(" bytes: + logging.debug("Decrypting the malware file, data length: %s", len(data)) return bytes([((b - 84) % 256) ^ 0xA5 for b in data]) def _get_malfile(self, username: str, sha1: str) -> bytes: + logging.debug( + 'Getting malware file for user "%s" and SHA1 hash "%s"', username, sha1 + ) quarfile = self.quarpath.format(username=username) quarfile = Path(quarfile) / (sha1.upper() + ".NQF") try: + logging.debug('Trying to open malware file, path "%s"', quarfile) with open(quarfile, "rb") as f: data = f.read() decrypted_data = self._decrypt(data) - except OSError: - # logging - print("Eset Error: could not read file", quarfile) + except OSError as e: + logging.error('Cannot open malware file on path "%s"', quarfile, exc_info=e) return decrypted_data def _get_metadata(self, path: Path, objhash: str) -> KaitaiParserMetadata | None: + logging.debug("Getting NDF metadata for path: %s", path) # metadata file has .NDF extension metadata_path = path / (objhash + ".NDF") if not metadata_path.is_file(): + logging.debug("Metadata file not found", path) + return None + + try: + kt = KaitaiParserMetadata.from_file(metadata_path) + except OSError as e: + logging.error( + 'Cannot open nor read NDF metadata for path "%s"', path, exc_info=e + ) + return None + except KaitaiStructError as e: + logging.warning( + 'Cannot read NDF metadata, mostly because of incorrect format for path "%s"', + path, + exc_info=e, + ) return None - kt = KaitaiParserMetadata.from_file(metadata_path) kt.close() return kt def parse_from_log(self, _=None) -> dict[tuple[str, datetime], QuarEntry]: + logging.info("Parsing from log in %s", self.name) quarfiles: dict[tuple[str, datetime], QuarEntry] = {} - for metadata in mainParsing(self.location): + for idx, metadata in enumerate(mainParsing(self.location)): + logging.debug("Parsing entry, idx %s", idx) if metadata["user"] == "SYSTEM": + logging.debug("Entry's (idx %s) user is SYSTEM, skipping", idx) continue q = QuarEntry() q.timestamp = metadata["timestamp"] @@ -225,25 +266,36 @@ def parse_from_log(self, _=None) -> dict[tuple[str, datetime], QuarEntry]: def parse_from_fs( self, data: dict[tuple[str, datetime], QuarEntry] | None = None ) -> dict[tuple[str, datetime], QuarEntry]: + logging.info("Parsing from filesystem in %s", self.name) quarfiles = {} actual_path = Path("Users/") - for entry in actual_path.glob( - "*/AppData/Local/ESET/ESET Security/Quarantine/*.NQF" + for idx, entry in enumerate( + actual_path.glob("*/AppData/Local/ESET/ESET Security/Quarantine/*.NQF") ): + logging.debug('Parsing entry, idx %s, path "%s"', idx, entry) res_path = re.match(self.regex_entry, entry.name) res_user = re.match(self.regex_user, str(entry)) if not res_path: + logging.debug( + "Entry's (idx %s) filename of incorrect format, skipping", idx + ) continue user = res_user.group(1) objhash = res_path.group(1) if (objhash.lower(), user) in data: + logging.debug("Entry (idx %s) already found, skipping", idx) continue - entry_stat = entry.stat() + try: + logging.debug('Trying to stat entry file, path "%s"', entry) + entry_stat = entry.stat() + except OSError as e: + logging.error('Cannot stat entry file, path "%s"', entry, exc_info=e) + continue timestamp = DTC.get_dt_from_stat(entry_stat) path = str(entry) From cde5dc726e5fd8efa0bb22ac83dda8bd1240415e Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Mon, 7 Apr 2025 14:14:22 +0200 Subject: [PATCH 08/40] Fix ruff error --- maldump/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maldump/__main__.py b/maldump/__main__.py index cb66a74..7ef12bd 100755 --- a/maldump/__main__.py +++ b/maldump/__main__.py @@ -192,7 +192,7 @@ def parse_cli() -> argparse.Namespace: def init_logging(log_level: str): numeric_level = getattr(logging, log_level.upper(), None) if not isinstance(numeric_level, int): - raise ValueError(f"Invalid log level: {log_level}") + raise ValueError("Invalid log level: " + log_level) logging.basicConfig( handlers=[ From 50083fe4d27cbc7cf62a8c9bfe680a0bfc2d34d6 Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Mon, 7 Apr 2025 14:14:51 +0200 Subject: [PATCH 09/40] Replace logging for each function by using decorator --- maldump/parsers/eset_parser.py | 56 +++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/maldump/parsers/eset_parser.py b/maldump/parsers/eset_parser.py index b35b584..2f07f36 100644 --- a/maldump/parsers/eset_parser.py +++ b/maldump/parsers/eset_parser.py @@ -19,7 +19,6 @@ import logging import re import struct -import sys from datetime import datetime, timezone from pathlib import Path @@ -60,6 +59,19 @@ _hashTypeHeaders = {"ObjectHash": OBJECTHASH_HEADER, "ProgHash": PROGHASH_HEADER} +def log_fn(func): + def wrapper(*args, **kwargs): + logging.debug( + "Calling function: %s, arguments: %s, keyword arguments: %s", + func.__name__, + tuple(arg for arg in args if type(arg) not in {bytes, EsetParser}), + kwargs, + ) + return func(*args, **kwargs) + + return wrapper + + def _infoNotFound(field): logging.info("Parsing data in ESET led to field not found: %s", field) @@ -68,14 +80,14 @@ def _warningUnexpected(field): logging.warning("Parsing data in ESET found unexpected bytes in field %s", field) +@log_fn def _winToUnixTimestamp(winTimestamp): - logging.debug("Converting Windows to Unix time") magicNumber = 11644473600 return (winTimestamp / 10000000) - magicNumber +@log_fn def _extractDataType(dataType, rawRecord): - logging.debug("Extracting data, type: %s", dataType) # Format: dataType_HEADER + '??' + NULL + objectData + NULL dataType_HEADER = _dataTypeHeaders[dataType] @@ -92,8 +104,8 @@ def _extractDataType(dataType, rawRecord): return dataWideChar.decode("utf-16") +@log_fn def _extractHashType(hashType, rawRecord): - logging.debug("Extracting hash, type %s", hashType) # Format: hashType_HEADER + '??' + NULL + hashData[20] hashType_HEADER = _hashTypeHeaders[hashType] @@ -109,8 +121,8 @@ def _extractHashType(hashType, rawRecord): return binascii.hexlify(hashHex).decode("utf-8") +@log_fn def _extractFirstSeen(rawRecord): - logging.debug("Extracting first seen") # Format: FIRSTSEEN_HEADER + UnixTimestamp[4] offset = rawRecord.find(FIRSTSEEN_HEADER) @@ -122,8 +134,8 @@ def _extractFirstSeen(rawRecord): return datetime.fromtimestamp(timestamp, timezone.utc).strftime(TIMEFORMAT) +@log_fn def _extractTimestamp(rawRecord): - logging.debug("Extracting timestamp") # Format: RECORD_HEADER + ID[4] + MicrosoftTimestamp[8] littleEndianTimestamp = rawRecord[4:12] @@ -132,16 +144,16 @@ def _extractTimestamp(rawRecord): return datetime.fromtimestamp(int(timestamp)) +@log_fn def _checkID(recordId, rawRecord): - logging.debug("Checking record ID") littleEndianIds = [rawRecord[0:4], rawRecord[16:20]] for littleEndianId in littleEndianIds: if struct.unpack(" bytes: - logging.debug("Decrypting the malware file, data length: %s", len(data)) return bytes([((b - 84) % 256) ^ 0xA5 for b in data]) + @log_fn def _get_malfile(self, username: str, sha1: str) -> bytes: - logging.debug( - 'Getting malware file for user "%s" and SHA1 hash "%s"', username, sha1 - ) quarfile = self.quarpath.format(username=username) quarfile = Path(quarfile) / (sha1.upper() + ".NQF") try: @@ -215,28 +225,30 @@ def _get_malfile(self, username: str, sha1: str) -> bytes: data = f.read() decrypted_data = self._decrypt(data) except OSError as e: - logging.error('Cannot open malware file on path "%s"', quarfile, exc_info=e) + logging.exception( + 'Cannot open malware file on path "%s"', quarfile, exc_info=e + ) return decrypted_data + @log_fn def _get_metadata(self, path: Path, objhash: str) -> KaitaiParserMetadata | None: - logging.debug("Getting NDF metadata for path: %s", path) # metadata file has .NDF extension metadata_path = path / (objhash + ".NDF") if not metadata_path.is_file(): - logging.debug("Metadata file not found", path) + logging.debug("Metadata file not found") return None try: kt = KaitaiParserMetadata.from_file(metadata_path) except OSError as e: - logging.error( + logging.exception( 'Cannot open nor read NDF metadata for path "%s"', path, exc_info=e ) return None except KaitaiStructError as e: logging.warning( - 'Cannot read NDF metadata, mostly because of incorrect format for path "%s"', + 'Cannot read NDF metadata, probably incorrect format for path "%s"', path, exc_info=e, ) @@ -294,7 +306,9 @@ def parse_from_fs( logging.debug('Trying to stat entry file, path "%s"', entry) entry_stat = entry.stat() except OSError as e: - logging.error('Cannot stat entry file, path "%s"', entry, exc_info=e) + logging.exception( + 'Cannot stat entry file, path "%s"', entry, exc_info=e + ) continue timestamp = DTC.get_dt_from_stat(entry_stat) From 23a77724521326fd83feef9f7fff0ec2b2ff639d Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Mon, 7 Apr 2025 14:18:47 +0200 Subject: [PATCH 10/40] Fix ruff format checks --- maldump/__main__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/maldump/__main__.py b/maldump/__main__.py index 7ef12bd..b518514 100755 --- a/maldump/__main__.py +++ b/maldump/__main__.py @@ -32,7 +32,7 @@ def main() -> None: # Admin privileges are required for optimal function (windows only) if sys.platform == "win32" and not ctypes.windll.shell32.IsUserAnAdmin(): logging.critical( - "The program tried to be executed on Windows machine without proper privileges" + "The program executed on Windows machine without proper privileges" ) print("Please try again with admin privileges") sys.exit(1) @@ -192,7 +192,7 @@ def parse_cli() -> argparse.Namespace: def init_logging(log_level: str): numeric_level = getattr(logging, log_level.upper(), None) if not isinstance(numeric_level, int): - raise ValueError("Invalid log level: " + log_level) + raise ValueError("Invalid log level: " + log_level) # noqa: TRY004 logging.basicConfig( handlers=[ From fa75b88895eef8237f704331d3f9bc72e140e954 Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Tue, 8 Apr 2025 09:13:24 +0200 Subject: [PATCH 11/40] Fix ruff format checks and return values --- maldump/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maldump/__main__.py b/maldump/__main__.py index b518514..30b7e5b 100755 --- a/maldump/__main__.py +++ b/maldump/__main__.py @@ -189,7 +189,7 @@ def parse_cli() -> argparse.Namespace: return parser.parse_args() -def init_logging(log_level: str): +def init_logging(log_level: str) -> None: numeric_level = getattr(logging, log_level.upper(), None) if not isinstance(numeric_level, int): raise ValueError("Invalid log level: " + log_level) # noqa: TRY004 From 55d3879efbf40ce2bc604d8f2ac6dd5ab05f55ac Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Mon, 14 Apr 2025 00:03:19 +0200 Subject: [PATCH 12/40] Move datetime import from TYPE_CHECKING --- maldump/structures.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maldump/structures.py b/maldump/structures.py index e9878b7..73e0a9f 100644 --- a/maldump/structures.py +++ b/maldump/structures.py @@ -1,11 +1,11 @@ from __future__ import annotations +from datetime import datetime as dt import hashlib from abc import ABC, abstractmethod from typing import TYPE_CHECKING, Generic, TypeVar if TYPE_CHECKING: - from datetime import datetime as dt from pathlib import Path T = TypeVar("T") From cfba55de76d868ebcdfbfee82d52d5f2a7053a73 Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Mon, 14 Apr 2025 00:04:39 +0200 Subject: [PATCH 13/40] Add Reader and Parser to utils.py This step is done to make opening the files and parsing the kaitai structs and datetime objects easier to maintain and easier to log. --- maldump/utils.py | 70 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/maldump/utils.py b/maldump/utils.py index e7ef456..c8aff95 100755 --- a/maldump/utils.py +++ b/maldump/utils.py @@ -5,11 +5,16 @@ import contextlib import logging from datetime import datetime, timezone +from pathlib import Path +from typing import Type, Generic, TypeVar +import kaitaistruct from arc4 import ARC4 from maldump.constants import OperatingSystem +T = TypeVar("T") + def xor(plaintext: bytes, key: bytes) -> bytes: result = bytearray(plaintext) @@ -64,3 +69,68 @@ def get_dt_from_stat(stat) -> datetime: logging.debug("Birthtime extracted successfully") return datetime.fromtimestamp(ctime // 1000000000) + + +class Parser(Generic[T]): + def __init__(self, obj: object) -> None: + self.objname = obj.__class__.__name__ + + def kaitai(self, kaitai: Type[T], path: Path) -> T | None: + kt = None + try: + logging.debug( + 'Trying to parse file on path "%s" to kaitai struct of type "%s" on <%s>', + path, + kaitai.__name__, + self.objname, + ) + kt = kaitai.from_file(path) + except OSError as e: + logging.exception( + 'Cannot open nor read kaitai for path "%s"', + path, + exc_info=e, + ) + except kaitaistruct.KaitaiStructError as e: + logging.warning( + 'Cannot read kaitai, probably incorrect format for path "%s"', + path, + exc_info=e, + ) + return kt + + def timestamp(self, value: int) -> datetime: + try: + logging.debug( + "Trying to convert timestamp on <%s>", + self.objname, + ) + timestamp = datetime.fromtimestamp(int(value)) + except (OSError, OverflowError, ValueError) as e: + logging.warning( + "Cannot convert timestamp to datetime, using default", + exc_info=e, + ) + timestamp = datetime.now() + + return timestamp + + +class Reader: + @staticmethod + def contents(path: Path, filetype: str = ""): + if filetype: + filetype += " " + + try: + logging.debug('Trying to open %sfile, path "%s"', filetype, path) + with open(path, "rb") as f: + logging.debug('Trying to read %sfile, path "%s"', filetype, path) + data = f.read() + except OSError as e: + logging.exception( + 'Cannot open %sfile in ESET on path "%s"', filetype, path, exc_info=e + ) + data = None + + return data From 7febc6c02e6d86578b64129416600b090b64b38a Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Mon, 14 Apr 2025 00:05:50 +0200 Subject: [PATCH 14/40] Move kaitai struct processing and file opening from ESET --- maldump/parsers/eset_parser.py | 46 ++++++++++------------------------ 1 file changed, 13 insertions(+), 33 deletions(-) diff --git a/maldump/parsers/eset_parser.py b/maldump/parsers/eset_parser.py index 2f07f36..8bd7778 100644 --- a/maldump/parsers/eset_parser.py +++ b/maldump/parsers/eset_parser.py @@ -22,12 +22,12 @@ from datetime import datetime, timezone from pathlib import Path -from kaitaistruct import KaitaiStructError - from maldump.constants import ThreatMetadata from maldump.parsers.kaitai.eset_ndf_parser import EsetNdfParser as KaitaiParserMetadata from maldump.structures import Parser, QuarEntry from maldump.utils import DatetimeConverter as DTC +from maldump.utils import Parser as parse +from maldump.utils import Reader as read __author__ = "Ladislav Baco" __copyright__ = "Copyright (C) 2017" @@ -185,14 +185,10 @@ def parseRecord(rawRecord): @log_fn def mainParsing(virlog_path): - try: - with open(virlog_path, "rb") as f: - virlog_data = f.read() - except OSError as e: - logging.exception( - 'Cannot open virlog file in ESET on path "%s"', virlog_path, exc_info=e - ) + virlog_data = read.contents(virlog_path, filetype="virlog") + if virlog_data is None: return [] + rawRecords = getRawRecords(virlog_data) parsedRecords = [] for idx, rawRecord in rawRecords: @@ -219,17 +215,12 @@ def _decrypt(self, data: bytes) -> bytes: def _get_malfile(self, username: str, sha1: str) -> bytes: quarfile = self.quarpath.format(username=username) quarfile = Path(quarfile) / (sha1.upper() + ".NQF") - try: - logging.debug('Trying to open malware file, path "%s"', quarfile) - with open(quarfile, "rb") as f: - data = f.read() - decrypted_data = self._decrypt(data) - except OSError as e: - logging.exception( - 'Cannot open malware file on path "%s"', quarfile, exc_info=e - ) - - return decrypted_data + + data = read.contents(quarfile, filetype="malware") + if data is None: + return b"" + + return self._decrypt(data) @log_fn def _get_metadata(self, path: Path, objhash: str) -> KaitaiParserMetadata | None: @@ -239,19 +230,8 @@ def _get_metadata(self, path: Path, objhash: str) -> KaitaiParserMetadata | None logging.debug("Metadata file not found") return None - try: - kt = KaitaiParserMetadata.from_file(metadata_path) - except OSError as e: - logging.exception( - 'Cannot open nor read NDF metadata for path "%s"', path, exc_info=e - ) - return None - except KaitaiStructError as e: - logging.warning( - 'Cannot read NDF metadata, probably incorrect format for path "%s"', - path, - exc_info=e, - ) + kt = parse(self).kaitai(KaitaiParserMetadata, metadata_path) + if kt is None: return None kt.close() From 80c107b8be1e4333a6170b1e60176e3b4728382d Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Mon, 14 Apr 2025 00:06:08 +0200 Subject: [PATCH 15/40] Fix logging function in ESET --- maldump/parsers/eset_parser.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/maldump/parsers/eset_parser.py b/maldump/parsers/eset_parser.py index 8bd7778..d1c2d67 100644 --- a/maldump/parsers/eset_parser.py +++ b/maldump/parsers/eset_parser.py @@ -64,7 +64,14 @@ def wrapper(*args, **kwargs): logging.debug( "Calling function: %s, arguments: %s, keyword arguments: %s", func.__name__, - tuple(arg for arg in args if type(arg) not in {bytes, EsetParser}), + tuple( + ( + arg + if type(arg) not in {bytes, EsetParser} + else "<" + type(arg).__name__ + ">" + ) + for arg in args + ), kwargs, ) return func(*args, **kwargs) From 82ef3d15e7dec30fc0fec608e4b5179ad963b01d Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Mon, 14 Apr 2025 00:13:39 +0200 Subject: [PATCH 16/40] Add entry_stat to Parser --- maldump/utils.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/maldump/utils.py b/maldump/utils.py index c8aff95..9f09ae0 100755 --- a/maldump/utils.py +++ b/maldump/utils.py @@ -6,7 +6,7 @@ import logging from datetime import datetime, timezone from pathlib import Path -from typing import Type, Generic, TypeVar +from typing import Type, Generic, TypeVar, Any import kaitaistruct from arc4 import ARC4 @@ -115,6 +115,18 @@ def timestamp(self, value: int) -> datetime: return timestamp + def entry_stat(self, entry: Any): + try: + logging.debug( + 'Trying to stat entry file, path "%s" on <%s>', entry, self.objname + ) + entry_stat = entry.stat() + except OSError as e: + logging.exception('Cannot stat entry file, path "%s"', entry, exc_info=e) + entry_stat = None + + return entry_stat + class Reader: @staticmethod From fc9bdb6adae6da39cd661a23a97b42693a37eadb Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Mon, 14 Apr 2025 00:14:07 +0200 Subject: [PATCH 17/40] Use new stat in ESET --- maldump/parsers/eset_parser.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/maldump/parsers/eset_parser.py b/maldump/parsers/eset_parser.py index d1c2d67..e18e71c 100644 --- a/maldump/parsers/eset_parser.py +++ b/maldump/parsers/eset_parser.py @@ -289,15 +289,10 @@ def parse_from_fs( logging.debug("Entry (idx %s) already found, skipping", idx) continue - try: - logging.debug('Trying to stat entry file, path "%s"', entry) - entry_stat = entry.stat() - except OSError as e: - logging.exception( - 'Cannot stat entry file, path "%s"', entry, exc_info=e - ) + entry_stat = parse(self).entry_stat(entry) + if entry_stat is None: + logging.debug('Skipping entry idx %s, path "%s"', idx, entry) continue - timestamp = DTC.get_dt_from_stat(entry_stat) path = str(entry) sha1 = None From 74f4f6da571e8dda36d903eed5a6b301dcc6b677 Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Mon, 14 Apr 2025 00:14:34 +0200 Subject: [PATCH 18/40] Add new logging techniques to Avast --- maldump/parsers/avast_parser.py | 112 +++++++++++++++++++++++++++----- 1 file changed, 94 insertions(+), 18 deletions(-) diff --git a/maldump/parsers/avast_parser.py b/maldump/parsers/avast_parser.py index 4843bf5..e7b2b6a 100644 --- a/maldump/parsers/avast_parser.py +++ b/maldump/parsers/avast_parser.py @@ -1,45 +1,100 @@ from __future__ import annotations +import logging import sqlite3 import tempfile from datetime import datetime as dt from os import unlink +from xml.etree.ElementTree import ParseError, Element import defusedxml.ElementTree as ET from maldump.constants import ThreatMetadata from maldump.structures import Parser, QuarEntry from maldump.utils import DatetimeConverter as DTC +from maldump.utils import Parser as parse +from maldump.utils import Reader as read from maldump.utils import xor +def log_fn(func): + def wrapper(*args, **kwargs): + logging.debug( + "Calling function: %s, arguments: %s, keyword arguments: %s", + func.__name__, + tuple( + ( + arg + if type(arg) not in {bytes, AvastParser, Element} + else "<" + type(arg).__name__ + ">" + ) + for arg in args + ), + kwargs, + ) + return func(*args, **kwargs) + + return wrapper + + class AvastParser(Parser): + + def __init__(self): + self.db = None + self.tmpfile = None + # Cleanup + @log_fn def __del__(self): if hasattr(self, "db"): self.db.close() unlink(self.tmpfile) - def _initDB(self): + @log_fn + def _initDB(self) -> bool: # Parse index.xml - self.root = ET.parse(self.location / "index.xml").getroot() + try: + logging.debug( + 'Trying to parse index.xml file "%s"', self.location / "index.xml" + ) + self.root = ET.parse(self.location / "index.xml").getroot() + except ParseError as e: + logging.exception("Cannot open and parse index.xml", exc_info=e) + return False # Decrypt vault.db and prepare db connection self.tmpfile = tempfile.mkdtemp() + "/decrypted.db" - with open(self.tmpfile, "wb") as f: - f.write(self._decryptVault("$AV_ASW/$VAULT/vault.db")) + try: + logging.debug('Trying to open temporary database file "%s"', self.tmpfile) + with open(self.tmpfile, "wb") as f: + f.write(self._decryptVault("$AV_ASW/$VAULT/vault.db")) + except OSError as e: + logging.exception("Cannot open nor write temporary file", exc_info=e) + return False + + try: + logging.debug( + 'Trying to connect to SQLite3 chest database "%s"', self.tmpfile + ) self.db = sqlite3.connect(self.tmpfile) except sqlite3.Error as e: + logging.exception("Cannot connect to SQLite3 chest database", exc_info=e) print("Avast DB Error: " + str(e)) + return False + return True + + @log_fn def _decryptVault(self, vault): key = b"\x92\xaa\xbc\x89\xef_\x1b\t\xaa\xad5\xf8\xadg\xe9+^Z\xfe\xdd\nt\xf8\xfb\xc3\xa5\x1e\xad\x87\x00\x9e\x16\x82\xec\xdb9(;w\x10\x16\x17\t\xdd\xef\x898\x8c\xff\xbbV\xf7\xa4\x01JU\xd7\xd6\xe2b\xda\x14*\x9c\x8a\x88\xe1\x8a\xb1\x8c5E\xbaZ\xa1\xae}6\x02ac\xa3\xf2`\xaa8\xf1~vv\x07\x1a\xd4\xc2I\xd4(e$\x98\xcf|\xf2\xbd\xc9\x92\x88\xce\x82\xdc\xc9q(i\x9e A\xb8\xea\xf7,\xb9\x9cRbm6\x96fY'\x90\n\xf9\xb5\x9a\x94\xcf\x9e\x96R\xb0\xeb\xdd&f\t\xe0\xe9Ls4\xc5Q\xb6\x1e\xdeHS\x01\xff\x89\xb2]\x93\x08J\xe0\x06\"e\x96\xefg\x8d\x89>\x86^\xd5\xcf\x03(\x08\x9c\xa0(\x8a\xd2\x07k\xc1\x81\xe9\x1a\xd9\xe5\xf3$g<\xf2nR\x13,,G\x07]K\x8dGOKn\xb2\x93\x13ZHR2\x08\x8cu\xac&t\xb3\x08\xba\xfci\xde\xcf\xeb?\xd9\xa0\x97c\xaa\xf8,)\x8b\xe9w\x854o\xa0\xa2U\xb1\x16F\xe6\x13\xda\xa9@\x87\xe0m\xdb\xdb\xef\xb2\x8cy\xa4\xfadX\xddH\xec\x97\x91\xf5\x05\xc5\xa4\xf4&63\xd6\xe8\xa1\x12\xd5\xe7\xb5%\x15k\x16\x05%\x0eZ\x17\x9e\xe2\xb1\"\x1e\"\xc0\x02\xa4\xfb\x1b%{-TI\x8a#\xd2\xdcO\xd5]\x9c\xa3j22\xb8\x01\n\x1f%m~o\xa3TW\xbb\xe8\x14?\xdf\xc2[\x81^\xd4\t\xd4\xb8\xb5\x9dX.\xd4\xf2\x18v\x13E\x88\xacU\xf2\x91\xa9\x0e'\xf2\xee_\xd1\xdb\x95\xbb\x8b\xb5b\x1d\xcb\xef\xf0\n\x01r\xb8D\x82\x84\x18S\x12\rL|\\Vz\x9c\"G4Y\xee\xa4g\xff\x1e\xec\xb2]\"\x04H\x07.P\x83\xd1\xd4\xbfZ\xb6\x0fa\xf28\xe4\xdc\xed\x18\x82\xdf\xae\x90\xef\xfd\xb3>T*\xcf\xf0\xb4{\xbf_8Bg#I\x1f&\xfe*]5\xcf\x1f\xbd\xee\xca6\x80#u\xae\xc6\xb3\xfbp\xb3\x9e\x80\xec\xb2\x8eB0\xb0\x13?\xab\x0e\xad\x0b\x91{\x16\xfd\xa4p\x92~NYK(\x1e\xb9WlW\x1e\x8d\x0c\xa1\xc9d\xd0\xb84\x13\x95\xd0acjP\x96Jf0\x15 \x17\xe1\x08\x06\x0e\x1f\xa0k\x89 \xfe,\xc2\xf1\x14\xfb\xbe:s&\x82E\x15\x80\xb7t\xa3R+\xb2'\x06\x89\xffZ\x80\x14\x98\xff\xe5\xac{\xc3^\xb3\x8d\xa5\x14\xf0\x08s\xd1!w{\x08\tl]\xe4\xc3Ys\xaan+\x1d\x19\xa9\x86M\xd5\xca\x87\xb5\xb4\x13\xf2\x06\x15\xfdKy\xba\x03 \xe1\t]\x0eyS\xc6o*[\xf5\x92JE\x0c\xc6\xa4\xd8\xa3\xb2@\xe1\x05\xf2\xd2\x9d\x9a7\x98wC\x93\x053\xae\xc4mL\xb3e\xe2\xb0\x9f\xcdE9O\xd3x+\xd4h\x9a\x159\x1ak1\xf4\xb5\xddc\xda\xb8~N\x0801P.\xb3D4C\x84<,\x99&\xf48n\xe5\xb7\xb4\x9fP\x10\x02\xb7\xc6P%v\x19\xb6\xa1\xe1\"\xfc]\xfap\x81\xa1\xa8\xc8\\\xc5\x00\x03\xc6)K\xae\xac\xd0\x15\xff\"cj\xc2vTW\x99U\x97\x7f\x88\xa2\xbd3\x87)\x84\xa2\x07M+a\xe5x\xcb\xcb\x13w\x15\xf7\xbeRe\xbe\x9eVg\xd2\xf6\xd2\t\xbb\xc7\xed\x98xW\xb0\x87Z\xf8\xf84\xe8\x87\x10\xcfv\x89;\x8c \xddJrJ\xd1u\xdd\x85S\x8b\x96\xc1\x03\x97]=E\x01\xbc\x93\xa4*\xfe8\n\n\x1d\xc9S\xee\xdcm\xdc3\xe2\xaf\xcc\xb0\xa2\xea[\x1a\x0e>\x1e5SEkM\xee\xca6\x10<\x18\xf0\xbaZ\xa3sy\xdf\xcf\x13D\xac\xbc_-\x0bc}\x87\x8cZ\x8b\x83\x8cw\xc8@%\xb1\x84u\x1d\xcb\x8eE\xe8\x82\x92*\x1e^\xf0\x99N\xce~,e\xf9v\xfc\xa7\x8c{Oc\x08c\x1aFH\xbe@\nr\x7f.\xe6\xfb\n\xfb@\xd7\"\x92\x15]\x00\x8aV\xdb\x01\xa6)3\xee\xcb\xf3O\x91\x9c\x1a\xe3\xbcD\xcdTG\xd0\xfe4\xf0XbX\xfa\x18\x1e\xe8\x01c\xff\xa2~)\xa1\x1cJ\x80T\xbd!x#\xba>w\x07>\x95\x92q\xa4\xd4\xab\xad\x8e\x1c\x87t>\x10\x03\xb1?H\x08\xafx7\x07|H\xfd\xa8\xf6y%\xe6Mp\xe1tIC\xaeJ\xb6\x14\xed\x1b[\xa5\x9b@\x04\xc7zu\xb0\x11\xb6\xaf\x1e\x0f)\x96\x00\xd9\xe5\x8c\x95{\xb5\x11\x02\xf3\xe0m\xc4U\xfc\xc5\x11\xb4\x89\xb4\"\xff\xbb'\xb8a\xf8\xaf\xbf\xea8\xebvG\x1d\x10qq\n\xdd\x9d\xdc\xf51\x0c\x91\x0e\xc0d\x0eUf\x88\x12;\x1fY\x89Kf\xc9\x9c\xbe'YuM\x18v\t;C:4z\xcb;\xeb\x01j\xda\xf8\xa2d\x18\\Y\x92\x0c\x86@\x1a,\xe3\x1e\x14\x96y\x08\x95\xe6RmP\xffT\xb8\x12\xd1\x82f\x80\xfd\xdb!\xd8nky\xe5\xdb^y\xa6`\xea\xe8\xbe\xcc\x91\xab\xb8\rVG\xa7d\xef6k\xb0L\xa2\xe8\xc4^F!\xfc\xcbc\x00X\x01\xcd\xf5*:\x1a#ck\xba\x9b\xdb4\xc9`@\x00;\xdaJ\x15WM\xa9\xec\xa9\xaa\x97\xea\xb0\x044\xb7\xc4*}\xc4y\xfa\xe4\x86\xbe\x83_\xac\xf5>B/s\xa5\xea\x8a?!KhY?\xb2\x18]j\x02+\x93V\xe5\xe9\x9b\x92\xf1-\xcaL\x94\x87\x12\xd3\x9e;\xb3\xa0\xc1 \xb9\n\xa9\x00\xf0\xd0\xc9\xa2\x8fj\x04\xa5\x02R\xf3\xb3\xbd\xe2E\xc5F+\x89'\x1c\x81\xd9&4\xd0Fn\xa6\x16\xa8\xc0\x99a\x15\xb8\xd9\xe5\xf6\x91\xe6\xfcb\xef\xac\xcc\xf3\xf1\xef\xa3\x04\xcc\x867\xc3\x8d\x1c\xc5h\xb8\xf94\x81\x07\xe3B\x0c\xdd\x82L<\x97\xa5\x92\xd3\x0b\x8b\xff\xa2]m\xaa\xc1\x1f\x94o\xf7{\xbaI]\x8a\xf57B\x85M#\x9c\xb1w+\xbd\x95\"\xd9\xe8I%\xe5\x19!\xdbY\xf2\xd6\xf6\xcap\x10\xa9\x1e|*\x96\x7f\x87\x18 Vs\x99g\x19\\\x08(\xc9\xa7\xa7\xafj{d\xcb\x9ap\x87\x13\xa7\xd3\r\xf0Z\x11\x8c\x8e\xf0\x94\x9d\x9c\xcb\x89u\xe7M\xed%\xa12\\\x1b\xaa\xccO\x0f\xaek\xc9\xfb\x0fP\xe4\x02\xd4 d\xf2\xa6\xec\xf2\xb3\x10\x91\xad\x91\x88\xdaaW_E\x10\xb3\x9b\xbc\xd2U\x849\xdc\xb5K\"\xe0\x12\x90u\x9b\xf0o\x9d\xef)1\xf7-V%(\x05\xc3\xfc>\xe9\x8e\xb0\xf4r\xf9\x1b)>5\xd6l\xaa\xa3\x8dg\x14N\x89a\xfbW<\x9bw'\xac|$P<\x8a\xf6\xdf\xce\x97\x816L\xb6+\x83\x80\x01\x07\x98C<\xc5\xefo\x8fi\xd02\xe2fb\x9e\x08\xdb\xaa\xbd\x9ba'&\x81:2\xc4\xe8\xbe\x1c\xc2\x02\xd8\xc4\xf8\xd16d\x82\x00\x1e\x03l\xf1)\x90\xda\x8c\xe9\x93\x91\xc1\xb8\xf7\xd6\xf5*\xc3\xf5#\x93W\x9d\xf1\x97\xa7\x87\x06k\xbf\xa4j\xe7a\x13iW\xd6\x9b\xbf!:\x1e\xfc\xd7:\x92\xba\x05\xc6\xa2L\xfd\xcfv\xce\xd2\xbe\x99\xc9,\xf2\x02\xa2hB\xa1\x14\xa1\xd7N\xa7\x90\xd4~\xac\x83_uz\xb0C\x9ff\x00[;2Hj\x0f\x96\x16\xe6I\xca~\xa5\x1e\xeas\x9bz\xe7!QMZZ\xfc\x01n\xdfl\xd3\x06\xf4z\x08\x0b\xe0\xd9Y\x02\xef\x98\x89\xa8\xcc\xbe\x17\xab\x08\x89Z7{\xa0nY6\x93\xa1\x12f\x8ac\xb1\xb0'\xac\xa2o\xdf\xf9}\xe4\xf8\xae\xda\xf2\xdb0*q\xd8\x87\xd2`\\U\x9bj\xd3\xcb\xec\nG\xb2U\xe0q\xe2\x85\xbc\xaa\xe4f\x0b\xaf\x00\xb7\xac\xc1}ez\xb5\x95B\x91\xdbT@\xd5K\xca\xc293\xa2\xceB\"\xa3\x83\xf9\xebn\x8f\x936\xfc\r}\xac\x00\xac{4\x1b\xceyN\xf3\xa7s\x06~\x12\x0e\x12l\xd3?\xd5\xb4\xc5aw\"[ \xa3\xc4\xc9J\xd0i\xf6\x0fe\xef\xdb\xe2\x9c\xd6%2%?Zq\x0c\xe3\xa3F\x0b(\xc8\xd1\x92\x9b\x1a\x06\xc9z\x12o\xde\x075\xd4\x1e4\xfe\xe3\xf7\t\xf5\xabtPu\x8bxwF\xbba\x8aX\xd0w\x82\xfa\nT?\x03@\x16\xc3>\xdf>\x82\xc9\xdc\x1a\xcf\x7f\xa3\x14\x83N\x95z\x1a\x1e\x1a\xd5f0\xc8\xf2z\xad1?[?Jj\xc8&q7X\x10\xc7w#R\x87\x81\xb2k\xcb\x19LNrq\xc7I7\xfb\xb0\x818\x14x.\xa6\xdcZ!\xe4\x8a\xad\xa7 \x81\xec\x0e\x85\xca\x86\xdd\xe9D\xc6\x1b&M\xeeW{[X\x87\x1d\t\xdcK \xd7\xfd\xceN9\xf5x\x17&\xd1\xa9\xe3q65\x84\x03\xbe\xc8\x19\x91\x9e\xbb(r\xe3h\xe1\xad\xb8\r\xf2\x8d\n\xe7t\xb9y\xf5\xf5\x1fq\x95\x97,\xe6\xe4\xbciQ\xdc\xab\xe2\x87)mh\xb3\xf7)\x82\xb5\xd9\x0c\xfeE\xff\x8f\xdc\x96\xb4\xca\xf1o\\\x19-\xd3\xbfa\x8b\x87\xaf\xd3\x05\xd18\\j\xa5\xd1\x87G\xd4\xe5\xc9\xd8)u\xf0o\x86\xfaQ\xad\x94\xcfK%\x1a:\"o\xcd<\x89b\x16\xd5\xf8\xd6r\xb2\xcdHO\x04[~\x14\xbf\xaa\xf1\xb4T\x8cu\x13\xf9\xf5\xd5\xec7\xa9*\xec\xc2v%\xbb\x98\x96\xb3\xc3f\xeee1\xd1\x7f?\xc0YwD\x04yn&\x92\x01\xd7M\nE\x88'\x08t\xd6\xde\xdeF\xcc\xf0pS\x153}Ut3 \x80\xb6m\xe8\x89\xdf\xcb\xb9h\xe268\x0f\xfb!~\xbaE}>o\xf6p>\xc3\xd5\xf7\xee\xa8\n\xf2\x8c\x81=P\x0f\x1a\xd5\x17\xd9\x16\x19\xb7\xfbi%(\x11\xd1t\xf2/\x90\x91PR$\xd7k,\xb2HE\x1c\x0ek\xe4\xa4\xe6\xc9\x8a\xb0Y\xa3\xa7\x1d=\x01\xe5\x00\xb6n\xa6\xd7A}9(D\xbd\xb5TJ.\x9d\xa2\xac\xc0\x91\xd1\x0bQ-,\x89\x15m,g\xde\x0e\xd9\x11Pa\xc5\xfc\xb7\tRY\xe5\x94\xc1\x01/\xe4\x92x\x1f\xfa%s\xd3\r\xb5\xb2O\x97x\xb0\xb6(\xa5R\x1a\xa7\xa2\xd4\xcd\x99\xfe\x05l\x7fh\xfa\xc7\xcc)\xfc\x1ee\xbe\xf7\xcc\xdb\xc2\xddg\xe1\x9cUL\xd7\xb4\x8e[+.\x03(\x19\xc8\xb6\xfd\xec:\xab6?^H\x04\xbdc\xb2\xa4O\x0bo\xc0(\x19%h\xc1\x87\xf2X\xa2\x05|>\x1fh\xcd\xa0\xd0_\x9f\x88\xfd\xbf\xb8\xd2I\xf1\xaf\xf4\x0c\xb2\x96\x1eq\xd0ss\x11\xf8\xf0\x06\x18\x97\xb5\xb2\x92g\xe7\xe5J{n1\xedUo\xb1\xd9C\xa1/\x8b\xe8R+\x167?\xf5\n\xdd\xac\xf2&\xd7\x07\xf6Nd\xe8U\xea\xecq\x7f\x85\x1a\xbd\xed@\x7fL\xfc\xe8\x9c\x18+\xb8X\xf1\x7f\xee[\x88x\x91\xcd\t\x15N\x16\x98?9\xdf\xd06\xb3\xee\x99\xaf\xddw\x00*\xbd\xd9\xaeQ\x04\xd8S\xd2\xbb\x0e\xa5\xf7\x06%w\xd9\x191\xe2\\\xdb%\x8f\xf7\x9b\xe0\x98\xf5\x1fx0-\x9d\xcb\x8f\xfe\xe0p\xfc\xed\xf1\xa4\x98\xacr|3\x82\xf0\xf8\xfd\x94\xb6\x8a\x14\xe5\xf2\x06\xaf\xee\x9e?\xcc\x10\xbf\xe0\x83\xcb\xdc\x7f\xcf\xc5\x13\xe2\x9e(G\x8a\xae\x84\xf9sJ_ \xbf\r5\xde6\xbf4\xa1\np\x9eC\x8b\xb1l\xa3\xa0PFI\xc0\xac0c\x9f\x08\xc7\x8b^\x1e/9\x95\xda\x8a\x8f \xe1 T2{^\x8e\xa0\xee\x0fc\x88\x82\x82\xafM\xc6\x05%I\xbf\xedb\xaeD\xf8\xfc}\xbb\xd2npd\xd8q\xde\xd6\x06\xf4Q\x80g\x8b6\x92\x8d4\x06'E\"\xa0b\xbc\xde\xc4\xa3#\x9eu\xdeR\x9b\x9aR\xc2\xcb\x04t\xd3\xf9pu\xe8\xb1f\xd4\x8f\x91\xdd\x9e\t\xab\xaa\x10E\xd6\xb4\xec\xfe\xca1\xcfnw.\xcbR\x80\x817\x12\x075X\xdf\xd5h\xc5Q\x1b\xcei\xc4-e\x16D\xfb\xfb]\x06\x7flz\xd8k\xdf\xb0\xd2\x910\x83\tr\xbaa\xee0\xe8V\x84\x03\xf7\x91H\xd5\x82\x9b5Q\xdbM\xb1\xaf\x07\xf0h\xba:\xbf\xd0zAr\xc8u\xaf\ta\x85\x83\xfc=\xa0\xb4\x99\xd0}0NxS\x16:\x15)\x1a\x80\xfc\xf5vf\xc8|\xff4\x8ekw2A.N\xfa\xd6\xd6\x1d\x93\xfc\x7f]'\xb2G\x84pBX\t4\x1e\xbdI\x84\xc5\x8a\t\x1e'W\xd7\xdc\xb2\xb3\x9aJ\x11\x83\xb9\xf1\t(]Z\xc2\xf0N\n\xb4\xeag\xefY+\xcc\x08\xa5\x07\xd3Z3?:\x9d\x96@\x7f\x9d\xc3p<_AD$\xbb\x8d\x1a\xc6=u\xab\xe6\xde\xc2\r\xf0@\r\x1d`?\xc1;\x98\xce\xef~z&\xc2r\xdeg\xaeH \x82\x91s\xfd\xdba\xd9\x1a\xad@\xc9\x01l\xd9w\x81\xb5\xd2\xe3\xc7:\xf1;\xbf4w;\x15\xf4\xe5\x9d\x0f\xe9\x94y\xaa\xa5\x04\x91m\xaf*&\xfd\xea\xe23k\xdd\xc4O%\x18)&~\xd9\xd2\x91\xd3\xc3\xb6\xd7S\xc1\x12\xdfm\x08\x8c\xcb8<\xe27\xfae\xb5B\xbbz\x8aL\xa7\xde2\x89\xc8^\x05\t\x92\x91\x0bp\x14R9Go\xa9v\x05q\xa5\xf8\xb4\"\xa0\xe8S\xfa\xba\xce\x87\xe1q\xccu\xf4S?\xdd\xc7\xc6v\x8d\xbc\x7f`\x04\xbc2\xd9C>8%.\xfb\x951\x17\xdf\xeb\x04![+W2V\xa8\x07]\x8c\xff0\x15O\xe2!AA<\xa5\x87\x06\xbe'p\x8ch\x05HA\x11u\x990\xcf\x96\x8c\xa2\xa3\x9a\x7f\x8a\x08\x0b9\xe2\x19-.\xc83?\xa7\xba\xe5\xc3\xeb\x7f.\x04=\r(FO\x08\xa0\xeae\xc6\xbbCMsP'&Iq\xf9(\xaf\x00\xa1+\x17N\xd1\xad\x0fV9Lp\xdc\x81\xc4\x04\xd1\xc7^1~\xf1\xcb\n\x95\x9bb\x1c\xcdj\xcdm2R\xdb\xe7\xf2\xfeB>9\xd6$\xb7\xeb\\\xbd\xa6\xd4\x0e\x04\xce\xb9\xad\xeeiqz\x8d\xcb\xceJ\xeb9o\xb8\xfa\xd6w\x82\xb2\xdd\\\x13\xdd3\x14`h\xd4\xfe\x1c\x9c\xded\xff\xfe\xc4^\x99]\x10\xfbq\xe6\xd6\xcf\x19gq\x80\x93\x84Ms\xa0\x1c$\xd1l\x8b(\x04\xbf\xcf\xf3\x8b\x08tV\xeb\xa9\xfe\xaeMDh\x1d\x9a\x84\xca*\xb1o\xb7\x81A\x9aj\x96\xf9\xfa6\xfak\x8b\x97\xdb\x1e\x8f\x94\xd7\x1a\x7f\xb7O\x1c\x97E@\nT}I\xdb\xbc\x95}j\t\xe0\xd3\xb9\x03x\x87g+\xb0\xf9P]\x01\x19\xd9\x95\xe6\x877\xd5\xcb`\x81\x12\xfc4\xd3\x9c\x08\xbf\xbd\xff\x18\xb0\xf5\xadG\xe4\x94\xd6\xde\xa2\xd3R\xd7-t\\#\xf8s\x14\xbd\xe6s\x12\xcfk\x0c\xfcq\xbb0\xbc\xf5S\xd2\x95R\x08$\xc6\x97w\x08\xee\x00{\xfdd]\x13UV\xe2\xce\x9a,2\xdb=\x04\x9bg\"\x9b\xea*\x8d\x03\xfdT\x1c\xc8\x8aI\x80\x12\xbc\xa6O\x93\x93\xf5\xaa\xfe\xa8\xd0\x8c\x13\xbfy\xba\xacw]\xaf\xd2\x07\xdc\x97\x86II\x9a\xc1\x08A\t\xaa\x0f\t\xd1\x04+\x8a\xe5\n.\x90\xc2\xc2\xdc\xe7\x9b\xb6\xe3\x1e'\xadc\xe0\xfdx\xec\xee\n\n\xb6\xf2\xdeEC\x18\x95\xe9\xfe\xff\xc0\x1d\xbaG\xdf}&_\x96V%W\xccY\x169o\x9a\xca\x0b\xa3\xf1\x19\x05\x8e\x1b\xbd\x90T\xb8\xc7\x13_3\x1dx;\xcd\xe2\xcd\xc4\xeb\x00/;j B\tf[*\xa2\xc3\xb7M\xa7rs\xd3\x8fc\xa2\xfa%\x05\xe2\xc7\xc4e\x07PoM\xbe\xd4\xa1\xf8G\x98(\xa6\x8b\xcc\xb4i\xbdm=\xdb\xb1\r;\x10bf\x1c\xd9o\x97\xd9\xd1\x01\xa0 #a\x17\xa2\xb4x:p\xf71\x93\x12\r}\x98e\xecq\xb2\x81\xf1o+z\x0f\x9f\xe0\x17\xcf\x940\x84S\x87\xc9\xa0\x05~v\xa92\x18y\xfa\xc7\xea\xc8A%<)\xa8Qo\xc4\xfc\x14\x96\xa2\x85Oq\x86;\x05\xf6\x8f\xab\x16\xf8Dy.@ \xa7\xfah\x1a\t\x02\x82\x01\xdeF\xdb\xac\x19\x0e\xf1\x982:\x883\xf9\xf4\xcb\xe5u\x0f\xa61.\x81\x11\n\x96\x97QK\xfa\x80\rGg\xf8\x80\xdd%\xf0\xb7\x84\x83\x1c\xe8\xf5\xe9\x87\x82aO\x80\xb1?\x9cMu\r\x02\xe17\xa6>p\xe5\x01!\xe9MXi\xa0R\xd9^\x90b\xacm\xc3\x07\xc0]G\xf6\xb3\xfc\x98A\xf3j#x\xd1Z0\xfe8(\xcc(}\xdep\xe4\xbb\x83\r\xd2\xb2\xb4\x0899H\xbc\xbc\xc5g\xb8\x03\xac\xfd\xd3\x07\x15\xf6\x15\xda \x16\\k\r9\xdf\xfe\xac\xf6h\xee\x01$\x89\xca\xb6\xefXpP`c`\xe9@\x94\x80\x10\x1a\xc3\x0f\x94Z\xdd\xff\x8b\xef\xebP\x1dj\x8aE\x7f\xcc4\xf1AbW\x92\x9d\x83Z\xd6\x80\xf7T\x85\n.\xe4\x0b\xd8\x8c\xae\xa4\xdd\x11P\xd2\x93w\x87\xdc\xa4\x00q\x02\xbfiD\xab\"\x80\xd0\xef\xb6\xd70\x1e\x00\xd5\x95\xb4f\x9d\xe4\x10\xfd\xf7o\xe4\x9aGU(\xf6~+\xd6\x17\xb0\x0ejF\x88n2\xd1\xdf5T\xc5.\xd0\xc6\xa5\xd5\xbb\xf3e\x86R\xe1\x8bX\xb7\xd3q\x13\xf3\xbb\xebM\xd2\xa0Y\x1dfG\xf0\xd5\\\xa1b\xcc'W$\xad\xa8>0\n\x07\xa8!Rk\xd5\xdd\x1d\xd0\xf4\xcf\x98\xa1r>}\x95UP/|f\xc7p\x0c\xd4\x17VAWf\x13`\x9e1\xa3\xadA\xb0\x8f)\xf8\x1c\x04\xfbQ\x95\x8c9_y\xe5\xe5\xc7\x06\xa7}R\xf9\xbbO\xe9}X\xeb\x98t\x8b\x19\x94\r\xdd\x1a\xbc\xfb\x01\x9bc\x96\xfe\xbc\x85 \xba\x11\xc8Gw\xae\xfb(\x0fs6\xe0zb=\xedo\x02\x84'S\x8c\x96\xdbH\xa1}\xe3h\xb8z\x08\xbb\xef\x1b\x98\xe8\xafY\x8b\xcb]\xa4\x14\xb8\xef\x90\x0b\xd9-\xadA\x04\x99P\xc3s\xc1\r6\xf3\xb5\xff\xf57z\x94\x1b&\xc07n\x83\x82\xe1\xa5\xe9\x8a-\xfb\xc92}\xba<\x83\x97\x05\x9d\x08\xcb\xe5\x12fdM7\x96Gm\xaaT\x9e\x0b\x80\xff6q\x0fAf\x10w\"9\xac\x81z\xac\x98\x19\xfb\x07sX\xaa\xf3\x08n\x11\xd6\xdc\x1c\xe6\tM@\xb4\xf7\x90%\xdbb\xfd\xe0>\xa1\x03\xd3\x0cx\xfd\xc6\xa4\x9b\":\x83K\xca\x03\xb0\xbe\xd8\x12\xdf}\xe2\xca\xc7\xc8;r\xd7[\x07m\xdfd\xb2\xdb\xd8\xc9\x81\x90\xa7\xe1\xf2\xcd\x1aSZ\xd7ULR\x95\xa1@qrq\x89\xab \xb5\xdd\xfa\x9bG\xd2A\x98\xef\xf8Y\x0b)B,\x01\x9e\xff\xf5 \xb0\xd3\xd0&\xa3\xe7S.\xbb\xbbf|\x80\xbc\xbbG\x1e\x97e.\xaa<\xda\xd5G\xc8h'\xfc\xc0\x9d\x95\x7f\x9b+\x91dVZ\x08\xc9|\x83)\xcf\xc3!\xf6\x93\xff\xbe\x92\xa0\x18\xb4\xec\x10X\xbf\x97N6'<\x8d4\xd5\x7fLZ\xe7I3N\x18\x14bH\x9c\x07](q\x0e<\xe12pg\x85\x17_\xef\xa74\xdf\x8bY\xbe\xbe\xaae\xb3>1\x99J\x9e\x1b\xe6\x05\xba\xfbWzp;\x02XhY\xd4\xd6\x7f\x87[\x0b\xa7=\x83\xacG*=\x90\xc6\x9cZC\x15sH\xf7+\\\xbe\x05_\xde1\x01\x10\x99\x95-\xcbr\xed\x95\xb9`\x7f\xae\xc1\xe3\x0c\xb3|\xb6\x88\xa3P\x96\xa5\xc5\xf5\x89KPs\xac,\x86K\xfb\xa1\x987\xce\xe0\xa0M^\xe4\xae\x9eG65=<\xc9.\x1e,\xe3\xaal9q\x1f\xae\xa6\x1d\xdc{\x90\xb6\xb1\x03\xe7\xa4\x9c\xb7\xa7y\xf1\xe7\xc2\xc1s\x91P Q\x901\xe8\xda\xbe\xb0\xe1g\x9b\xdf\x1bC\xed=\xbaL9\xc7\xf5b\xa6u\x14\xceli\xda\xf4mx\xe78U\x8fF\xe3\xafa\xe9\x00\x1a\xf5q\x15z\x94\x1d|M\x0b\xdfx\x04\xa5\xb0\x80\x0c\xd3+\x97\xaa\xdc\xf5\x9co\xd1\xe7o\xa3\xeaC\xefZG\x93\xa1P\xbc|\xf4%\x8b\x80\xb0t|\xd2\x80X\xae\x8e\xf8]\xc5\xc1\x86{\x06\xe8\x98\xa5\x1d\xf5D\xfb>\r\x0c\x0e\x17\rME\x05\xa1\x87Xg\xdfP\\\xae[\x18\xf5&~$\xee\xb6\x19\x9f\x98|n\xce\xba\xcc\xcd\x06\x88\xfd\xd8O\x9a\xf5\xb3d\"\x13\xa5\"9\x0f\xab{\xc8xw\x11;\x90d=w\xe3\xb1\xd2\xa1\xeb\\'QX\x1b?\xa0=\xb4\xe6$\x17N\x8b\xc1\xd9A\xa8\x92\x97\xe6\x92@\xf3\x07\xfc\xbeT\x97\xecku\xcdV\x90\xf31\xdc\xaf\xc7\xf7\x8e\x81}`\xeew\x93\x7f~M\x80\x91\xf2@\x07\xe3u\x97\xdavF{\x7f\x15\x89\xa6\x00\xca\xd4\xb0\x0e,5\xb9\xd3\xbb\x8bZ\xc8\xba\xc1\xddP+bF\xbe/K8\xc7\xad_\x84\xd5a?\xdadR\xe6.\xdb\x15#\x8b\x9d\xaa\xce\x15\xa7q/\x04\xab\x00\x9dj\x16\xdc\x81f\xae\xf7s\x06\x84,P\xcf\x98Z\x94i\xdb\r\xfb\xc8\xc2T\xe7\x19\xbd\x1a\xc3\xdb\xb1\xd6`KJ\xc4g\xd3\xf4\xa9\x1a\\NW\xc6\xcb*!;\x9e)\x8ej\x1c\xb8u\xb9d\x80\x8bjg\x9a\xec\x18\xa2\xc5>]+,f\xc3\x16\xee\xc8dr\xec*\xcdE\xfe\xd9e;:\xc6\xefN\xc5`\x83\xb7\xb1Y\xea\xa3v\xd5Ng<\xd1\xa6g\xee\xe5V\xe9\x9f\x80\x16\xc8\\\xf7\x04\xe3\xf0\xda\x07\xabe`\x1a\x94\x8c]\x89r8\xf4\xcb\x9a\x0b\x0e(\x9a\xd8e`7s\xaa;8Bbkz\xc2\xe2\xe7\x9d\x95\xdd;A\xda\xd1\n\xd4\xe7\x9a\x01\xcb\xfb^o\x8e\xfb>\x95%s0\xb2\xcc[`\x80\x88B\xf5\xcfT\x83K\x1c\xcf2\xaa\xac\x97\x8f?\xc8g\x0b\x16\xa1BP\xdeZ\x8e\xce\x0e\x07x\x04\xd2\x0c;\x98J\xe6\xb5+\xc8\xa0dT\x9b@\xa3\xa5\xc8\x0c\xe6:\x12\xcfg0X\xb4\xb6\xf1\xf8T\xd8\xf8\x0b9^\xd3\xb2\xe5\xd0\x8d\x93oV\xef\r\x19\x86])\xd0\xd1J\x94\x82L\xa3\xdd\t\xaca\x9b\xc9\x18\x02:?\xf1\xbf\xe78\xba?\xa6\xe3\xd0\xb3\xdeL8*\xd7\x9fSd\x18\x8b\xb9\xa8M\xa1\xdf\x17@\t\x9a@=wZ\xd9~\x9a\xa3O9\xf0\x0b\x93!\xa9+\x9a\x96\xea\x89\xc5!7\xe1\x95L~\xe01\xcdQ\x92X\xfdJM\xf9S\x13\xad\xab\xce\x9f\x1ck\xfcP{M\xa0a\xa7\xd8\x8c{\xaa\xdb\x11>\xdc\x8az(]l\xa3U\xdb\x15+\x9a+\\8\xc7\xbd0\xc1\x98\xc9O\xb0\xfb\x07i6\x98I\x1d\x1a\xe8b\x9bc)\x94x}\xd1y\x86\x94\xe6X\xd4\x1c\xa1\t\x9f\xdb\xe4Z\x16\x8e\xa2Z\xf9\x8boj\xf0\xbd\xa8e\x92\x13\xea\xb8\xf4\x99\xa9]\xf4!\xf6\xbb\x9c\xc8\x1b/\xf5zR7\xb6u\x7f\xf8\x929\xbb\xf5\x12\x02\xc6\x1e\xdbm(>\x94\xe5\x17\xd3\x9c\x03_0\x05\x16\x93S\x90_\xc2\xd5\x00s\xc8\xe1\\\x9dk\x93\xc1\x1e2,\xbc\xe4,q\xf1\xa2\x16\xf1\xac\x95\\g\xe59\x1a\x1d58\x1c\xce\x9d\xa8kp\xff\xc7\x0c\xf6j\x82h\x13V\xdd)\xee\xd9(\x01\xc7eN\xa3W\xb6\xc9\x83x\x92sM\xde}\xa0V7\xdf\xc9\xeb\x0c\xe30\xf0\xe1\xbdOUQ\xba\x1f\xd3\x03\xffr\xd3U;w\x06n\xaf\x89\xd4\x8f?\xe0\xea\xa8\xea\x03\x18\x89\x9f\xdf\xdc\x023!j\x84\xf3\x87\x8e\x01b\x9b^\xf5\xda\x94\xfe\xbba\x7f\xe0?\x17\xc1\xffb\xab\x05\x81\x99\xffH\x19\x07\x91\xfe\xc4\x7f\xf4r\xa63j\x83\xce;\xa9\x08\xb4\xd6\xd7\x99\xf7\xe3sm\xb5\xc9hmAD\t\xbd\x89@\xfd\xeb\x9b\xf4\x85\xcb\xa8\xedG\xbf\xc3o\xaa\xeb\x9cK\xf8\xf9\x08*\xad\xa2\xe7\r\xd0i\x8df\xe6\xf6\xc3n\xbf\xd0\xe9\xe0M\xb4\xf1[lf\x16gS\xa0\x9f*\xcdWI\xa8~\xd6\x10]\x8c_\xb8|\x19 \xc4\x00\x93~\xa7k\x9c&\xbf\x9a\xefhU\xdd}\x14V\xe9\x11\xed\xe2\xf3\xeb\n\x0c\x87e\xb49\xf3eh~\xbc\xe5d\x1b:\x0c\x06\xf9\xffJ`\x96\xd1\x82h\xfb\x94\xe5\x07E%\xae\xed;i\x9e\xaf3\xe4R\x8c\xef\x0f\xae?\xf9Va\xc74\x12\x8f\xea\xd5\xde\x8e\x90\xcd\xbe\x15\xf6\xf1\xa2\xf7\xda8.\xeeR\xc8\xa7\x8a\x1e\x90\xa8-\x97\xf9\x1dl\xcf\x9e\x08\xa8SQ\xab\xf2\x8e\xb8Y\xd5A\x930s\xa2\xe85\x89-\xf5\xf1\xf1\\\xcb\xa9\xe7\x8e\xffn\x9aXut_:`\xeb\xf4\xc1B%{H\xc9\xa2\r\x0f\x1f\xbc\xcad\xfbdI\x1f\x8a\xa7LZ\x98^\xda\xda\xd2\x9e\xe4L\xaeS\xa4PD\x91YT\xcem\x1d\t\"9jepP\x04\x13\xca%\x06\xb9\x96\xf3|\xa5%\x04d\x83\xb5\x87\xe2b\xa5@\x1f\xba\x07\x97\xe8>S\x8a\x82:\x8f\xbb\x0f\xb2\x86\x8a\no\x8bd\xbf{\xe4\xa2\x8e5\xc1\xd5\x8b\x9e\xd0\x87\n\xe4\xd2\xafv\xb9\xe7\xba\xfc\x17\x01\xbd\xcc\xa4Q&Fl\x1cy\x87\xb2\xc7B\x8d\xb0\n\xab\xcdC\xd6\x9d\xe9Wp*\xa8j\xbe\x82\x91\x13\xda\xb1^\xf6\xca\xb7\x14\x85\xb1\x07(AH'g2\x00\x89\xbd\xcb\xf30h\xf8\x1b\xf4\x867\xcd\xfe\x1a\x1d/!\\\x85Y\xd2\xa1\x03\x05\x17\xe6\xd1m\x99l\xb1:\xb1\xadu\x8a\xef\x91H\x81\x81\x12\x8bc\x1e\xc5\x06\x0e\xadMbY:\xf2\xc0\xb3\x1e\xe3\x1d\xd0O\xda\xb81\xccP\x11\x82\x12\xd5\x91$\x7fU\xd2m\xa8\xa0\xbd\xb3\x8f\x9dMfL\xd474\x19\x81c\x81\xb1\xab]WTt?\xc3\xfe\x7f3\x15\xbep\x02:\xaeV\x8e1\x00\x06\x12G\x1d\xa9K\xbc\x93Dm\x8b\xc5\xb9\ta()H\x11\xd0z\xf6\x10\xf8\x9c\x01]W-DM!\x121\t\x01\xdc\xf1n8\xab\x82+\x1b%\x0cG\xf9\xadAt\xfb\xc1\x05\x81`:\xfe\xc0\x17\x92f\x14\x119\x80\xff\xc3\xb2=\x8d\xa5i\x86`\xf1\x06\x81\x1b\x9b\xcau2\xf1\xe5\x82\xe4\xe3\r#u\xae4\xb0E&\xd8\xacy}\xa3\xe7\x0c\x8c\xce\xaaJ\x8d\xe4\xcf+\x04\"U\xb5\xb7\xafF\xaf\x97\x04\x94}\xfb\x88\xdb\xca\xc0\xe2\xd8\x08KU J\x0fe\x16N\x92\x06\xbbr$n\xa1\x0e\x08ed\x946\n0_\xb3;\xb3\x9d\x0c\xce\xc7\x85]\xa5\xf7b\x17\x82\x7f'\x8c{dg\xb9T]N\xc6;[\x9a~[\xcd\xc4\x02\x98+:*\xae\xa7%\xc5{\xc7\x05\xb8\xfa\xc6\xc5|\xe9\x92G\xa4\xb1\xa6G5\r\x94.\xbf=\xc9\xc3\xc8R\x0fa\xb5X*\n\xc1\x11q\xf37\xec\\\xf9_n\x7f\x08\x1e\xffV\x95y1Nx\xb9\xbaIJ\xf9\x14W1\xb4\xdb\t\x01r\x1d\xc4\x1a\xa0m\n\xb6p>/\xae\x05Z%P\x88$v\xa9+\xdd\xa8r\xf7B.\xd4\xd4\x97(\x1a\x14X\x94\r\x0f%WU(\xb4\x10\xdb\x14B.L.\x1a\xca\x184|\x9c*\xca\xa8\x82\xe3\x12:\x1c;\xa5\x83\xe4e\xebp\x12[\xcc\xf1\xb3\xd3a\xd3\xf9\xd8\x1f\x94\xd54\xdeX\xe2a\x9b\xa4tn8\r5\xaaX\x99\x0e?\xf8#l|!\xaai\x0f\x17Y\x98\x85\xc9b\xa8\x1cK\x11H\x05\xaf\x8c\x05\xab\x87pgwX\xe8\x7f\xc9\xd0jU\xd3\x1drs\xfd\x07\x95S|\xd3\xe1\xba\xf7?\x8d\"\xf6px`\x8e\x04\xea \xee\xb8\x15\x9b\x15\xa0\xb9W\x1f!\xbf@\xd6\x85|\xba\xab\xe9w\xa4\xa4\x11&\x8a\x14\xfcl\xe9\x94\x1e<\xdd\x92\xa7>\xf6+\x1a\xf4\xee\xd0\x08x\x1f\xe8s\x18j\xc7BAsi\x9bN\xc5\x87\xd5!\x8f\xe7\xd1\xedQ\x162#H \xcb?\x8a\x8d\xa2(\xbf)`\x7f\xac\xaa0S\xfb\xcf\x15j\xd7FU\xf6\xd4lT\x1b\xf3.x%\xdb\xb1\x12ttBQ\x89\xccF\xd7\xa5\x12\x05\x13\xbcM\x8d\xc3\x7fr\xe2\xfam6\x88\x8d\xaeK\xc2\xb1\xa8\x82\xd1lb$\xa7\xffB\xf8\xa3\xe8\x89:Bpe\xe6\xde\xcf\x91\xe1X\x18\x00%\xb4\xeeTs\x05\x1b\xeb\xe9\xe4\xa1A`\x1e\xf1\x00\xfe\xd7lj\xe3$R\x1b'K\xe48\x14)\x04\x02a\x8c\xe4\xae\xc8\xa5\xfb\x82\xf3\xb3\xd40\xd5vH\xf2\x94\x8c\xd1\xc0\xfa\x8f\xaeO\xbd\xfb\xf3\xdc\xd4\xc25\x81\xb6r\xffD\x113e\x9be\xab\xb0\x1f\xef\xf6\x8a\xbake\xc2\x1f\x93\xfa\xa5\xe9b\xb0I\xeb\xa3f\xa0\x8d\x02N\x88\xe3\xe7f\x01\x0bYQ\xf1LR\x9f\xf9F\x9a\xcall\xf2UN|c\xfek\xb7\x08\x8d\xd5K\x00M)(\xd4C\x11\xd6\xb3\xd1\x19\n\x08xyAb\x17'\n\x08\x19\xaa\xe4F\xbd&\xaep_\xdeV\xdc\x1c\xd4\x02\xb9M\xe9\x08\xbd\xec\xbf\xb4\x8f{\x12\x98\xa6\x10&\xa3{\x92\xd9j\x91zo\xf9/\xcd\x84p\x1e\xc5\xb7\tI\x84\x0f\t\xdc\xb5g+\x94\x84\x82\xc6D\x1f\x13)\xb3\xa0\x8e\x8d\xba\xd2\xc7\xe3\xe9e\x8bS/\xd8*6\xd5w&\x86:\xa6\xe8\xdd\xd4\x929\xe3/\x8b\x8flrj\xa7S>]A\x8a\x12\x9apC\x1c\xca\xf8\n\x1d\x93\xd8\xb7\x89\x7fF\xea\xcf\xbco\xf5T\xbb%\xbb\x12\x04K \x8a.6s\x03\xed\t\xda\xa3\xa6\xc6\x920\\\xc2\x8bm\xa8\x9e\xa0\xa7.\xca\xb1\xdc13\xa0(\x8dP\x12@3\xfb \xb0M\xaf1\xa3\xb8vMb\xab\x88E~\x1b\x81W\xda\xfb\xed\x97?k\x17X>\xca;o\xb3]H\xe7\xf6>\x84\xd5n\xaa\xc8)\xb7\x89\x0f<\x9c\x0c\x0fZ\n\x14\xfel\xcfk\xa0\xba\xec\xf0]\xc2%\xa2\x9f\xb9\x93\xdc\x8e\x7f`-\x08\x7f2k\xad\xc9\x1b\xbd\xc3\xd3\xfa\x06\xc1q\"\x13jR\x9e\xa2N>\x18\xfd\xa4]bb\xc7b\xd4|\xe4\x1b\xa4,\x9a\xdb\x80\xf3\xf7!\x1d5\x8f\x9d^D\xca\x97\x8cCn\x80\x86O\x94\xf5\x8b3\xb5\n$\xe7\xa2\xaaI\x84\xf0\xca\xf3#Q\xd1\xfe:\xb6\xa9\x15\x98\x05\xea\xb6g\x81(\x00d\x15\xef\x87\x80\xd2iU\x96\xe3Q\x9a\xd7\xa0\xc6\xdbJ\xa8\x13\xf7[,:\xe2mQ\x1c{5x\xeb\xd6\x99\x92\xba\xea\xad\xd7\xa8\xa1N\xd6\xb3u\x08G \x8co \xc1\xe2\x93\xe5\xfc0/\xcd\x9d\xb8p\xab\x88\xb1\x80#\x12\x00$\xbf\xc7h=\xf6\xdb\xb2\xff\x02W\x93v\xbf\x867\x06V+\xc4\xe4\xef\x93\t\xac\x0b\xc8&\x87\xd8\xf1\xa4\xf4b\xac\xd4\xa9\x97\xd04\x89 \xbcWK\x03\xc4\x8dOu\x80\xd1\xeb\x18j\xfaXK\xb6\x02\xb4\xd4M\xf7\xce)\xb1\x94\x90;\xd4\xeb\x9cX\xabG\x9fF\xf0\x10\"$\xe9\r\x91\xa64\xf8\x15f\x0b\x86K\n-1\xe2B\xc4\xaay\xeb\x05\xbfm\x0c\x8d\xac+T\xb4~k]v\xe0\xc9\xc8\xa0\\?\xd6\xc3o%g\xa9T\x97\x03\xb1\xa5\x88\xab:\x9c0\xc6\xb8u\x14\xb4=v\x91\xec\x01\xa63\x83\xb8\xea\x9b\xef\x0fQ\x03!p`\x9a\x14\xae\x19\xf2\x85N\xd6\xb4\xb6?f4\xc6\xa2\x89\xa1\xef\xae\x8a>\xba\xfa\xb8\xf4\x9f\xd5\xd3\x14\xeb\xb4:\x0c\xbc\xe9Si\xa8\xff\x19\xb3\x0e U\xbb\x0b\xc8\x8c3\x83Oa\xd4@\x15\xcf\xb5\xda\xbdXMt\x1f\x15\xf9\xbc\x1b\xe9\xd9\x9b\xa21\x11\x9bI\xc4B\xdcME\xe2\xc2\x04\xeaI\xf0?|\xf0\x99V\xde\xafL\xe04~-vg\x15\xbc\xed\xc4\xf63;\xa8\xfa\x1a\x1d\x16\xdc\xf2\xb6I\")\xa0$\xbc\x86B\xbf<\x97\x88\x83\xae\x13\xa7\xb8\xe9\xfb\xc0\xfb\xe3\xbb\x95?\x1fH\xfd\x9ab\x99\xb6|>\x08\xb9_DN(\xb8n\x9c{<\" I]\xd0F7;N\x19)(\xe3P\x80\x7f\xae\x12\xe5Y\xb20S\x90n\x1e\x01\x88}\xcb\xfbXC\x9d\x94F\x1a\x1a5\xda\x85\xc43\"iH\x06\xb6\x82\x00\xdb\xa5\x96\x90\xa4|\xfez\xc4\x9a:h\x04g\x0f\xc9+\xc6\xcac-\x90\x00'\x17\x8e\x0c\xc8\xb8?\x90e\x02\xc3!\x15\r\x03\xc0\xb2\xf5\x17(`\xac!\xdf\xfe`\x92(\xeb\xf3\xf9\x8e\x9c7\x00nGo\x18~\"\xfb\x85\xcb\xfa\x0f<\x93E~\xcd\x80\xa8\xd2\x96\x83!\xb3\x80\xcd\x81\xde\xdc\x9b8\x03\x04\x80^\xbbV\xcce\xe2!#PD\xaf6\xc4\x1f\x92l\x89\xae\xc6\xa6\x12\xf0PY\x9d\x11\xb5\xa0\xca\x14\x8e \xd1\\\xcb\x14\x84\xa9\xdd\xba\x16;\xdc\xe8\x8c\x02\x1e3\xbb\xaef4|!\xc4\xb5K\xa6f[e\x12\xc5\xe73\xca\x00#\x81\x07\xcf\xc6\x98u\x91\x12\x14w\x04\xc8\xe5\x82Z\x1du\x06\x04\xd6\xc2\\\xca\t\xb5\x0cx\xd2\xb5\x92\xac%\x9c%\xe4\x03\x0b)\xb0I_g\x9e\x91\xa6\x04\x01~2q\xf1/W\x90P\xb5\x88\xcf .\x97Y\xda\xd4\x920\xe6\x9b\xb0j \x1b\x16\x0b\xc7\xec\xa5J\x003\xf7D\xf5%\xf2}\x84\xb5\x12\xbe\xb4W\xe8\xfeii\xef\xbe\x1c\x07\xb7T]\xeb\xe2\x18s\xc8\x8f\xc7\xee\xe7r\xd6\x84\xc8\xfap\xfb\xa7\xb2\xf4\xa3G\x9c\xa0G\x98\x9d\xba\"Z\xbb\xcb\xdb}\xd3\x99\x07\xf9\x02\xa3'\xb8 \x93\xafs\x88)\xb2\x0eB\x075\xc9\xa6u2\xd4\x13\xae\x19\x12\x14\xefE\x9f\xb2&\xd6\xfe\xa8\xabY\x0b\x1ac\x18q\xfc\xb8/\x95\xc2#f\x8e\x8b\x7f^e\\ \x0b\x96\x08\xb5\xa6\xd7\xd9[\xfe\x88\x8c\xffM}Z\x13\xd8\xff\x8a\x16J\xa3\x89@-\xdf\x9721\xf7\xfa\xb2\xd2;\x00I\xc9\xb0>\xf8\xd8\xee2\xa3\xeb\xbb\x0b\xe3J\xc8.e\x8e_K~9\xa3\x9b\xe0\r\x8b$\\\x13\xb8\x8f\x1a\x19O\xbb!a\xc3\xff\xec\x85e1\xfc\x98\xff\xcc[\xd9\x07j\x1d\xea\xb3\xb5Z*\xa6g=\xfd\x9d\x1bc\xd20\x88\xde\xa0\xfe\xaf\xca\x08\xa34\xb2\r\\\x01\xfd\x97\xf0\xc3\x81\xd4\xbf\xb66\x0el\x1f\xd5c\x1b\x9d\x96\x06\"k\x9c\xce\x91Iu3\xb9q\x19\xb0\xf5\x08\xcdc.\x04\xfd\x7f\x85\x1d,\xe5Jb\xab#^\xfc\x008\xb9\xe5\xf5\xb94P\x9bk\xa9\xd1E\xbb`\x02O\x9e-8`\xd0\xe3\xe80<#\xcd\x8a\x03\xdc\xfcT\xf3\xc0\xd19r\x81\xfc\x94\x9f\x7f\x95\xab\xad\xaf\xccpN\xa9\xc9v\x7f\xf9\x7fF\x8c\xbc\x00\xf5\x99\xd1u\xb5^s\xa9\x8f\x98(\xca\x187\x9a\xd2c\x82~\x04\xea\x97/\x19\xa1N\xf2c]U2a\xd7\xbe\x83\xa0\x82\xa2w\x11&RV\xa4/\x94$]\xeb.\xd9j{$\x96\xe8\xd9\x82\x81\"\xd8\xf3\xc9\xce\x89\xdc\x00=5\xa5}\x15t\xafc\xb0\xba;\x1c\xdb\x94\xc1\x0e\x8a9|\x05U&\x1d\xa0\xf3\x19\x89\x13\x8f\x87!\x88\xac\xd4\xe5\x99\x00Q\x80\x11'A\x12\xa3A]gJE\x9f\xc0t\xc1c\xcf\x98\xa6\x8a\xc3\xd8\x8aF\xbd\x00\xe1\x01\xaf\xca\x98*b\xb0F\xfd\xefP/&V\x00\xec\xb7\x0c\x95\xc4\xe6\x80:\xb7W\xa8\x9b\xce:\x01\xb2\x90\xaa\x9f\"\x14\x05ul\x90\xc9~b\xa0\x1c\x9f4:Q ~\xdfh\xcec\xb2(\x87\xbb\x1b\x9a\x92\r\x97X\xed\\\x0b\xe1\xec4\xbb\x9c\xe7\x89\x1dz\x94x\xfe\xa6Rx\x12\xc3\x86z\r\xf3)\xce\xf0G\x02\x1aG\xca\x87\tl\xc0\xac\xd0\x92\x1c\xf9\x87Kny\x8c&|\xf6T\xe4\xd1Sn\xd3\xf34w\xee%u|\x86\x85\xceQ\xe1\xd3\x80\xaak\xf2W\xde\xda\x1b+\x18\xb4\xd9\x86R'$\x0f\xa8\xd2\x17\xc9b\x15[\x8d\xf1kd\xc7\x08s\xda\xf3<\xc1\x1f\xe7\xd1.l\x0fmd\x00\xe9f\x94p\xda\xbeE\xb8>\xbdKa\xc7'(\xedIs\xc7\x8c\xe0\x92\xec\r\xfb)\x0c\xdbJ\x80\xf8\xca\x07RP\xe3\x94\x1c\x86;\xa6\x1d\xa4\x1cs\xc3\xd7\x92\xe4\xbb!\xde+\xce\x1e\x04\rw\xac+\x832\xaa\xbbop\xb3f~\xc1\x9b\x86\x91v6\xc9\xfd\x16\xf3tX\x99d\x04Q\xc1\xf4\xe4]n\xb9B\x14\xcc\xb9\x02Q\xd9=\xe9M\xaco30O\xacq\xb9;s\xfb\x01\x1cT\xe7;\xc2\xd2\x0b\xa3\xd97Y\xb9\xa0\xcf{\xafdw\xab_\xb7\x992\x81\xb3\xb4l\xfa)\xf9_\xf9;\x7fO\x94C\xe8\xaa\xfb\xa2MT\x8f\xdf8\x96uV4\xc1\xf35G\xcbj$U\xd6\x1f#@\x87M\xe1\x15B\t\xa7S\x1a\xa5\r\x98\xc2\xf8\xbf\xa8%@\xbevYj\x85\xa8\xf5\xe3n\xd0/L\xda\xed\x19;k\xbb\xb5{d^\xc2I\xff\t\x0e\xf6d\xcf\xc3\xcb\xa9[\x9b\x04\xe9\xba\x0flj-\x86\xd8\xc41\x9bA\xd0P\x83\n\x103\niI\x86S\xaeK\xf5\x8f\xf5\x89\xde\xc9#\x97\x98U\xb3\xa2d\xde6\x0f\xcd\x08\xd3\xb0SA)\xdf\\)]\x9f\x90\xd6\x84*\xbc\xe8AY\xb7]\x05\xe6\xc6\x8b\x96\xd8\xa1\xe8m'\xe74z\x0e\x87\xb3\x814e\xc8Aw\x07\xec\x8ah\xe5\x9b{\x0f\x8a\x8cG\xaao2\xd4A\xdfA\"VZ@\xc3^\xe3\x8b\xc8\x03\xca\x99S1g(\x08\xe9\xe7C\x8aR\x9b\xc4\x9d=YQ\x87\xd5N\xd5\xbf\x1a\x13\x84r\x03\xc7\xc9$Q\x805\xedWv+dZA\xa5m\xd3\x11*\r\x1f\x00$;\x99g\x06H\x00\x9f\x93\xfa\x16\xda\xaa\x99r\x91\xc2\x14\xfbmm\xfafn\x0c\x82|\xb6t\xb8\x83\xd7^A\xc4\xe4\xf0\xbc\x98\x17\xa9\x17\xe7,\xd7\xc9L\xfa\xa0xH\x95d\xa6\x82\xe8\xff]\x11\x11\x9c\xa8:\xe6~\x1f\xc0<\xc3\xbc\xc3\xe3\xff\xd0\xa0\x8b\x98\xde\xa8\x9d\xf2y=n\xa6xj\xc3}\x04f\xc7\x06!\xb2\\\x19M\xcd\xb2\xbaH\x84!\xb9\xc7\xea\x1a\x8fi\x7fh\x06\xf5{\x9dYg\xa0b\\<\x9c\xe0\xc4\xae`\xec\x17^\x01q:zn\x9aJ h\xae\xb8\xbe\xad#O<\xc7\x83)\xe1\x86,\xd9}\nM\x05\xd2\x86%\x1b\xfb\xfb/\xd7\xd9?\x1fD\x8c\xc0\xfa\x7f\t\x1c\x81\xc9\xa3\x93~\x1e\x8f\xe2\xddc9\x04\xb0\xb8\xe5\xee\x1f\x88\xedaq\x86D\x9b7\xc4\xdc\x99x\x9c+?8N$w\xc8\xa7\x17\x0e\x00\xef3\xe1\x8f\xfb\xedp\xca\x82!\x92H\x08PE\x17Ot\x13\x0c\x01\"(\xd2\x1b\xbff=\xd6\xf0P\xed\xed\x83\xec.\xda\xb4d\x02\xb3v\xf6k\xef\xa3\xfc\x14\x82\x16\r\xb5\xe8quE\x0bE\x16\xedq\xca\x97\xbf\xbd^\x92\xe1j\xbc\xf5\xf0\xfc\t\xf8\xa6\x9a;a\x18\x10\x04\x07R\xa3G:qQ?Ee\xf5+\xd6\x7f\xec\xe9\x1e1\xb5[\xe3h\xd1\xdcY~\x8cj\x12\xb3\xb9\"\rj\xeaX|\xbe\x9ej\xb9'\xc5\x9c\xfcE\x9e\xfd\xe7E\x95\xab\xff\x87\xc5\xb6\xe4J\xfe\xe3s\x04\xc5B\xce,\x01H\xeb\x04\x03\xc3\xe1\x1a\xa4*\xcdnq\x99\x87\xbb\xf5\x92\xdbf\x94~z\xdc\x14]h\xd2\x91\xb1\x8b`w\xb4o\xd4\xc2tv\xfc\x0b\xde\xe1\x81D\xcf\xc9J\x91G\xb7\x07X\x0e\x12\x1c\xde>K\xb9!\xc1\xeb\x9a\x8fF\xec~\xdc\rF\x9e\x10\xe7;J3\xcc\xdb\x97\xfe\x03\x8e\xdf\xb7\xa4Ax2G\xd7\x8d\x08\"\xf6\xea\x03\x8c.(=^9\xdf\x12\x95\x10ME\x97\x0e\xda\xe7I\xdbcw,\x81\x16\n\xcdW\xe9\xee0\x01M\xb3\xe0\x8d\xc2O\xc2\xd7\xee1f\xbf'y\x1b\xf3*\xb68\x01s\x1a6:\x0b\x80-\x12\xbc\xc8_\xc6\xfc\xbfe\r\x08n\x81\xd2w0\x0b/\x94\xef\xb6\x02\xf9\xc1\x04\x19\x05\\h\xb7x0U\xff\xc7\x9e]k\x9a\x9f\xe4\x17\x18)S\x13\x89\x80\xfc\xb4\xb6V\xd2\x1f\xe8D\xcb\xd4\xec\x08\xcb5PA\x05\xf8rwb\xdd3\xe7\x19N\x9f\x8fw\xe4\xfdK\x97\xc6e\xb5D~\t\xc4\xfa\x07\x0e\xfd\xa9S\xbd\x91\xf1r\xedB\x86\xf1\x96\xb4\xff9\xa8|\x14H*\xf6W\xd8\x9dO\xb3\xdf\xf8\x8f\xab\x0c`Z\x9a\xcf\x81 \x06\xff\x9f\x8c\x9c\x11wCb\x8a\xbe\x89\xcd[wv}q\xc5Ah\x8e\xb4>\x01\xb6\x0b\x0e\x84\xa8\xc4\xdf\x9a\xa8\xfd\x99\xba\x80p\x9a\xc2\x8f\xabk\xebq\xc1\x96\xbc\x972\xb8\xf7\xed\x80\xd5xfF\xec#\xe528\x14\x97\x08\x95e\xb2~=\xb1\xe6j\x83<\xe9\x9b\xf0\x12\xcd\xe8B\x8e\x96z\xca\xafQ\"4\x99\xdc\xa8^\xfe;\x89e\xdd\xd6\xb4G\x17\xea\x1a\xa3\xbf%bb\xca\xa3\x05.r: \x10Z\xdf\xd4g\xb3g\xe6\xb2\x96Nw\xed_Z\x16\xa5]X\xa3w\x14f\xe1\n\x9d:\x0c\xf82\r\xbep\xa8py\x97U\xc6\n\xe8D\x89Q?\xc5\xe2\xca}\xfc'\xc9\xf5\xf1\xbc\x9b\x94\xb3^P\xbd\xc5.'\xc6\xc5\x11\r\x86(\xee\x95>|\xfbY8r\x89o{\xe4\t\xb9C$`\xaf8\x7f\x16E\x16\xac,\xa2\xabue\x86h\xcapa\x0b`\xad\xb6\xcf\xd83\xa4\xb6\x11\x9c\x8f\xd7&\xd9\\Y\xfdo\x1a\xed\xf3\x02\xca\x9c`E\xe3\xc8\x16c\xd0\x13\xbc\xe6\x9c8\xed@\x89)\xefA\xfa\xee\xc3\x9ej\xe9\xb2\x05\xc0\xaah1_\x0c\x03\x1f~\xb9/T\xb6\xc0hM\xe4S`\xc48[y\xee%2\xa9\xd0\xf8\x1fs|\xba\\\xd5\xad\xf4/\r\xb2\xd2\xdc\xf0_?\x83\xd9\xc6\xa3w\xb7\xfa5\xf1'\x1a\x8e\x1c\x92\xd9\x12\xf7H\r\x11\xb0{\x01\xc9g\xee\"]\x1c\xadBr,\x8cS}\xcb\xf6o 8\x82Ca\x80\xa8:}\xce\xa6\xf4\xd3\xea\xa4\xdf.\x16Y\xd3\xe8\xb5\xee\xe5{}N\xb3\xb4d\x8amq\x8a\xa4\x9f\x15\xc8/l\xe2\t\x96\xc5\xe8*\xba\xbe\x1f\x1f\xd1\xab+7\x01(\x9e\x9b%\x05wX\xff\xe1y\xd2\x8e\xf0\x9aB\x02\xfcz\x00~\t\x11|\xb6\x8e\x94\xb9=\xdc\xf8\x83\xa5C\x14\xcd\xac\xad\x83\xe5\x9b*\x0f\n\x8b\xc4\xfc\x14\xefW-\x0e\xecVs\xae\xe0\x86\x83\xd1B\xbe\x02XN;xC3V\x1a\x10\xea\xbaVM\t*\x00\x92\xa7\xb5~BB\xf2\xb4\xd3U\x93p\xbfd\x16%\x9c05\x84fN\xdb\xf9\x1b5e\xa0&\xad\xbcsNuY:l\xd3ib\xb7D\x83@\x1c\x9dK\x9b\xf0q\xf2o\xb4[\x97o\xddUy\x9f\x93\x03\xff\xb9\xec\xd8Q\x8e\x11Q]\xdb\xe3zz\x89\xcb\xca]Z\xd3\x01\x02\t\xc1o\xfc\xa9\xbd\x1a\xf9\x8a\x85(9\xbf\x8e\xdd\xb8\x9cm\xb6\xda\x95\xe4\xcb\xbdel\x7ft^G\xa8|\xfe\x9f\x90`\x9c\xad\x87W\xdc7\xdb\x887\x11w{\xb2\xae\xbbtt\x06\x81\xb4\xec2\xbcz\x8a D\x16\x0eO0Q\xc0\xd9\x84\x8a.\xe5Q\x9d\x8e&\x9fa\\A\xfb@\x86\xf7:\x82\xbd\xf4\x13Z\xeb\x86:QJ]?D\xa9\xa8g\xb4\xc1\t\x87;14\xb6\xe2'i?I\x1eHs\x94Z\xe1\x19\x7f\xb2\xf5\x90\x9eK\xe9\x1e\xed\xd7\xe3\xe6\x0c$R\x88\xfaB\xc8\x92\xde\x05@\xda\x96\x92G\x87lE(\xaf'\x9e\xae\xfaR\x1e\x0bC\x9eH\xf7\xdf\xe3\x9f\xe0\xf9T_t\x8bB\xcahh\x81\t\x98\x82\xa1j\x17R\x1f\xf1fTl\xec\x91A\xf1t\x1aR\xb7\x7f\xb3\xbcBZ5\xb8\x1co\x9eN\x1d.g\xee\xf7$\x85\x87f\x90).\x10\xb6\xf7q\xf9\x94zP\xb7\xdb\x9b\xd39\x1d\xc0\xd6\xfe\xff\x07x\x1c\xfb\xaf%\xbd\xbc\xc6\xba\"\xf6|\x10\xd75\xc3+\x18\x1a\xfb\xb4\x11\xed\\\x8fh\xd9\xc0\t\xa1\x17\xccZ|Z\xb1\xb8\x8e\xc9#\xf9\xd6\x8b\xbf\xdfn\\\x96\r\xa0=0\xbc\xe8\x84\x0b\xef\xeeR\xfe\x1f\xf7@\x02\xbbR\xe9\xbb\xcb>\x8fS^\x0f\x92\x7f*\xf7+\xcd\xca\xdc\xc8p\x06)\xc1 \xcdz\xab\xcb8B~\xaf{}\x19\xc6\xeb\x8b\xdd{j\xe0\x01\xe4l.\x19\xd3T*\x8d\xc7H\x07k\x8b\xfd\x8eg\xcd\x89\xaa\x8a\xe6\xfb/E-X\x8a\x89\x02\xa2\xcd\x13\xacN>\xbc4a\x18W\x02\x95\x9e\xa4z\xff\x05\xf5\xa9\xb0,`*\x11}\x1cz)1\xf1\xe0\xb8\xc64\xc8\x032\xcc%z\x80\xb1\xec\x7f<\xc4\xfentJ\xd1\x10\x90\xab\n\x96E\xe2\xa2\x00L\x1dO\xe2\xaet\"B\x0e\xf4\x8d\x8c\xb7\x8fA\xbe<\xcb/z\xd6\xae\x02(\xb8\x9dL\x85?\xe7T\xba\xd7\x961\x8d\r~\xa0\x9e\xe0\x12\xd1-\x8dc\xb8\x06\xc4\xa1\xfe\x1d\x8f\x03\x86\x9a\xeeh\x1c\xdb\xb8\x96\xfcc\xfa\xd4\x13\xfaX\xa4#N\xd2\x0c\xfe4\xbdB\xb1v\xa6>\xbdE\x9c~\x1f\xc3\x17u1C_\xa5\x84d\xe8\x9f0\x9f\x98A!\x16+Go\xe6s\x95EA\x8av\x1c\x1d\x83\xabZh\xef\xe2zS,.\x1d\x91\xfe)\x19l\xfeyAR\xc3\xa1>\xe6\xb1\xef\x9d\xaau\x1f\xf3\x86Y\xf6%L%\x932T\xf3\xbc\xcckX\xf4\xebGa\xffV\x92M\xd0C\xd4Kn\xee`\x98\x84;{P(\x9be\x01;\xd6\x16#88\x0c\xcd\x97\xd7\x14\xdf\x0c\xa0\xedDc\x82W\xe6j\xa6\xbbH\xa5\x9d\xcb\t@\x0b\x10\xfd)\x9ai:\xd4\xe1\xbcU\xfdLs\x9d!\"2iRI\xe5\x93\xa1'\x86\xd8\x90\xbe\x96\xc5\x04ul\x15\x95`\x8b\x17\xeb\xef3U\xf5[\xbcV\xe5\xbf\xfc\tq}\xb9@\xb9+\x80\xb2\x02&\x7f\xc7^#\xa3\x8c2\x862\x19\x12\x97\xbd\x06\x86i\xbck)N\x05\xe7A\x13\x9d\xf0?\xd0\xe0\x10\xe7Y\xd0\x83\xf5\x1e(\xaf\xaf6\x04\xb6\xe5\xb0E\xa0\xa6\xe1\xa7\xcc\xd1\xbe\x89\x9f\xf1 b\xee\xecp\xa8\x08\xdf\xdb}1\x93\x97\x984yG\xe1\xf3\xb8\x14\"4\x1cfL,\x953\x88O\xb4\xfcv\xa2\xae\x9e\x10\xc8\x91\xa7\xc7\xcb\xff<\x90\xc0ojKK\xf2\x16\xfc\xf6rm=p8SJK\x1b+oey\xedp\x8e\x81\xa9\x9c\xaf\x12x\xc3\x8c>L\xd1\x82\xe2\xbb\xc8\x16\xc5\xf4\x0eQ\x9f\xd6\xf8\xf55wu\xc9\xf8\x0e\x0f\xf183\xa2Mc-\xc5\x80Rpu\xcbJb\x84\xb1\x1f\xc2\xb9\xc1\x07\x96\x9f\xe5n[N\xc8\xafW\xfb}2qM\xe2\xc9\x8b\x19\xe0\xc2\xc6\xc5\xc4@\x88\xf7\xca\x88\x9b\x0cC\xd0*\xeb\x16\xeb\xef/\xb3P\x96\x1e\xf3\x8e\xc9\xbf\x975`%\\\x04\x15\x91\x89TV`\xc1O\xea\x89E=7\xfc\x9a.\x98\x8c\xe7\xd0\x86\xf5+\xd7\xc0[g\x0e\xab\xe1\xed\x07\x10Q\xbe\xfc\x93 \xd7;5\x93?\x85\xa41Y-\xd23I\xf9\xf8\xb2\xc7\x7fX\xe7x'\x87fF\xbbp\xeb\xda\x0f\x94t^\x84\x8bz\xeb\x1b\xaf\xba\xb9A\x95\xd8\\\xca\x91\xea\xc3I\x97\xd4\x86\x8d\xffM\x9b\xde\x82AA\x9f\xab\x17_\x9d\xd8f\x87\xc3\x93(U\xd8\x8a\xfc\xf7%\xd1\"\x0c\xcb\xc8\xa2\xbe\xe3\x0b\x11\xd0\t^\tHf\x15\xac\xa7\xd6\x0ekDq\x036O'\xf6\x86\xfdS[{u\xdf\x97\xc7\x96\x9b-\x88\x9f\x86\xece\x8c\x83\x8fi\x9c\x8dw\x04\x13\r\x1fP\xea\xa6\n\x94\xc3\xf3\xcfvw\xe0\xa5R\xcaf^\xf5u\xceU\x85\xd0\xb3]\x85\xe8y\x8di\xcc\xd2.j\xc7\x97G\x1f\xd8>L\x18\xd1\xba\x04y\xd6\x83R{y\xc4aqB\x0c\xc8Rm\xb7=\xf6\x0e\xc4\xa8\x98Y\xe5\xd6\xa04\xf7c\xc9a\xd5\x07\xca\x11\x80\xcex\xcbb\x97#2\xec\xf3\xca\x03\xf7\x95\xcb\xc9\xd3=\x8ed\xdf(\xd2Y\x16^TiJ\xa5\xa0\xaa\xb9\xb3q\x90\x9f@\xb0\xb0\xe1\xc4l\xa3`C\xcd\xe5\x864\x064/\xd0%\xd4\xce\\\xfa\xd0P\r:\xb6x\"\xa8lsK\x06\xcb\xc2x\x83\xb7[\xf4.d\"\xf6\x02Q\xf8X\xf1\xf8g\x1cc\x03 R\x1b\xa7\x15\xbc\x97\xb6\x0f\x7f\xd0\xf7\xcb\xea\xfc:s\x1ay\xdf\x19\xdd\x12;\x02T\x8a\xf3\xa2\x84q\x04\x9bi\xaf\xc9\xe9*\xf3\x98\xe1#\xa1\xf9\xe8\xb0\nl\x8c\x12\xee\xc1\xcfH\xa3\xb3'K\xf4Ot\x19\xacY\xd0?=\x90\x0bV}\xf3+\xc8;l\xb2\x00\x14\xde\x04\x7f\x15\xed\x1eP\xc1-@\x84\x17\x7f\r\x95\xf59\xf3K\xbb\xb8\xa8Y\xe7\xc6\x976\xb0g\x04\xfc\xbe\x15\x9a\x9d\xb6\xa2yfW\xb1Y\xab?\x8f\x9c\xe3\x94\x07\xa8xP\xe5\xbe\xb8\xa3\xe9\xf9c\x88\xda\xb1\xc4\xbd@\xab\xdfe\xb0R\x99\x85y\x808\xdf<\x99\x1c\xd8\xc5\x00\"\xc3\xfd\x92\xf5\xd9\x91\n\xdd.a\x11\x9a6\xe3\x15=hyB\x96\xad\xbe\xf6\x84\"\xf2\xa0 \xa1Ux.\xb2\xc3\xba\xcc\x14x\xf0mK|\x1c\xd9\xd5m\xba\xe8\xb3C\x1di\xd3\x8f91\xaf\xd5\x8e\\\x0c\x19BM\x13c7\xc7\xed\x1c\xf7{JBy\xb6i8q\xcdT~^\xce{\xef\x91$\x85\x883\xc2v\xf1\xb0\xf5vS\xa7\xe0\n\xc5>MTc\x9d\x7f\x01!\x14\xf3x.\xee\xbd\x10#o\x18\xba\xdc\xf9\xf1\xdd\xc0.\xf3\xe3p\xb5`\xd7\x97\xe79\xc1\x8bP\xf4\xce\xc2\x1c\xfa\xc1\xa94\x7f\x1e]Q\x7f\xfa\xdf>\xa7 S'\x8e\xe8.\x8b\xc6y\xa1?\x1c;\xac'\xd00\x0cP@\xe4R>\x06\x15\xb5\xb4\xce\xe8\xdc~\xd4\x8bI4\xf6+\xe5\x82\x1f\xed\x04\xa7\xb8\x9a\xa9\x8a\\\x18\xc6z\x08\xc9\"\x97SE(\xa4KH7<\x8c\x06\xad\xb6\xe45\xf1\x0c{\xff\xad\x81\xe8\xf9\xb6\xe7\xc5\x90\xda\xb9\xea\x05\n\xd5\xd2\x0b9\xcb\xc9\xce\x89\xe0AT\x1c\x0b\xb9]\xb0\x07\xcd\xddWe)B\xb39\x9f\x9a\x0b\xce\xb4<\xa2\xef=\xd0\xc5\xfb3\xf6B\x9d\xd6\xb1\xf68\xff\x16\xd19\xc63\x81M\x89\xf0\xf67\x9a>(gzO\xcdt\xc7\x91\xe3\xbd\x81\xcc)\xa7\x14\xba[\x99\xcc\x92\xbb\xfa\xce\xa1\xd0n\xaa\x91b\xad\x1cb\xfb\xc3j\xda\x9f\xf4\xcf0\xb7@\x8e\xf5{\x14\xedU\xbc\x1d^\xeb\xe8v\xb5R\xc7T\xadR\x04iP\xf5\x7f\x9c\x0e\xf9(w\xd1\xa39`K\xea\xff\xe5\xb4\x7f\x90D\x0e\xf8\xc7\xeb\xc5q\xe8\xa5=\x94\xf9p\xca\xa0\xcf\x01\xeb\x8f8\x87\x00y\xfcm\xdd\xcff\xb8N\xde\x02Lv\x94\xeb^$\xc8Q3\x90g\xf1nMmC\xe31\x81\xb5\x10\xcb\x16\xab>\xef\xf3l\xe5\xc7\xc4>x\x88\xb8\xb36\x1be\xa41q1}^\xf1i\xa4\xde\xff\x10\xc1\xaaJ=\xa0w\xdb\x07R\xd9N\xed\x87\xb5\x04\xa8\xf2we\xf9\xca\xbc\x14\xf5\xb3\x14\xef\xf8\xc9\xcc}\xcc1;\xba\x95\x9d\xe5\xc2[#\x86\xbbJ\xa1\xa0Z\x04\xd11\x00\xe8\xbe\xade\xb6\xa3\xfaaG\x98\xa5Ad\x81#q9\x03d\x9fr9\xdf\x12y\x1fP\x8d\xa5\xd3XYA\xd4\x8c4cA\x8d\xa1\xc7]?6\x176\xa0\xc40\x1c\xd0/\x9an\x97\x1fUW\xac\xb6\xc5T\xbf\x15K\xac\xedoz\xd1e\x83tc\x99\x8f\x93\x108{\x0e[\x82M\xa1\x04\xd4\x1b\x8b'\xf9\x14\xf1\x13\xa4\x16\x83\xc9B\x9f\xaf7\x9b\x04\x9b\x15I>\xd2I<$$|\x823v\xec\x0c\xdd:%\x88e\x1f\x9ap\xa9\x97\xf79\x14\xbe=6t\x99\xc4>@}w=dn\xd5_\x90\xa3C\x91\xc5'\xd1\x8f\xaf\xbb\x05\xc5\xe8\xa2\x80\xf03d~\x0c8\xa9\nm!I\xadvX\x0f#\xdd\x0b!\x0eq\xbe5tP\xfc.\x16\xe8D\x94A4\x87\xa4\x17Y\xee&\x1f\xaae\x1d\xd3MCAG\x1dg\x82|}\x8e\t.\xdeuO\xd1B/\xe3~\xc5\x88\xa6\x156'\x07\xe2\x06\xb7\x07.\xfb\x8f\x1d\"3ju\"7\x13R?\xa3f\x16\xf4\xdb\x0c\xbe\x8b6\x8b\x8a\xaf\xd2\xa6\x9dm\x8fUg\xbb\xb3M%\xff\xcaG\xb2w\xf2\xec\x03\xb9^?\x98Xeiyh\xe0\xe1\xb0|\r\x1ax\x1a\xd4s\x03\x7f8\xfa\xc7qKk\xb8\xb5`v\x1e\x81\x10\xbe\x81\xff\xa9,\x95X_r\xd5\n\xe5\xd4\x98k\x03\xd9R\x9f2|\n\x85\x82!&R\xa51om\x97\xce_\xd64\xfe|\x92\xc0\xb4\x95e;@\xd1)\xdb\xf0n9h\xb8$*N\xe7\xcc\x05\xe1@\x136vs\x1a\xab_\xaed\xf6\xae?S\x1c\x9f5\xdb\x03\x04\x1c\x11\x8b\x97\xa3\x12-\xff\xdao\xd5\xa8!=>|h\\BT]\xd9\x93\x7fK\xfa\x07\x9ch\x9aa\x9bX\xa2X\xd6\xb7)D\xfcs\xc5P\x94\xfc\x05\xb2\x05\x04\x96\xcc\xaf\xeb\xe4\xd2g\\\xbf\x0e,\xfe\x012.{\x00[\n\x93\x00\xd2r\x96ZO\xe3-\xbc\xdc\xe3\xcc\xf7P\n\x19\xd4!x\x0b5\xa9\xe2h\xc7\xce\xb8\xa2\xb3%\xd6<\xd0\x94\x98\xabh\xd1w\r\\x!o\xa1n\x91\x12\xacT\xc3\xa9&Y\\!\xcb\r|t\xe1W\x92E>\xce\xc2\x95\xf0\xcc\x1c\x02\xbbR\xf5z`\x13\x1bh\xbc\xe0?\xd5D\xd3\x1a\x94\x01^N\xaa\x87\xa0\xd2\x19\xa8\xbc\x94c\x93+\xc2\x90\x01\xde4\xb5.\x1a\x05\x91\x18\xab\xb8\xf1\x06$i\xf3\xe41\xca\xf4\xa58\xac\xe9D\xd5\xea\x19\x7f\xf0\xcb/Q\xceWl\xc8k\xbe$\xc2'\x0b\x7f&\xfa\xe5\xc8\xa4\xd6\x0f\x19U9\\\xcb\xa8\x15\x0b\x89\x8cD\xd0\x13\xbe\xbd\xfe9\xf7\xea\x08\xc1\x17\xa3\x91\x97\xaf\xdbN\xfa\x0c\xabV\xdb\x19\x05\xc7\x8ei\xd5\xbe\x83\xb1'\xdf\x96\x03\xa5_\x9e\x0f\x0b\xf1\r\xec\xfb\x0cp\xa3\xfd|\xf8Lb\x80\x98B\xc2\x98\xf3\x91sx\xbe\xcc\xb9\xc1&+\x98Z/\x07\xa1Y\xfd\xedy\t\x9c\x91\x8d\x12\xe7\xf2;\xa3Z,\x99<\xce<\x17\xcfG#\x16\xf1\x9f\x81y \x18u\xea~\xed\x9594\x8e7\xcc\xf0\xb6\xf2#mA\xb0~\x1d&\x00\xa1\xaa\x99P\x80\x1aSs\x01\xfe'Kbr\xebts\xb0\xe7\x08\x93CWW\xbeA5\x9e\xd5B0\xf2\x863aV\xea6\x827\x95\x03\xd9\xb0Di$u\x82b\x98\xf1\xd5\xe1\"[iTVf\tFo36\xb2K\xd0\xb3\x8b\xd0\xe0\xb7~\xb9\xe2\xd9\xf3r\x18\xdf\xe8\x1f\xcaP\xf7:Z\x1d\xdd\xac\xd5\xf4\xbc<\xba\xce\xfd\xf5\x106Z\xd0\x12n\xab\xdc\xce\xc4\xbcz\xf1\x7f\x90X\x8e\x9b=\xae!Y\xcf\xc6\x87\x94\xdd\x91\xae\xdcD\x06\x0f:\x95+y+\xa7\xff\x01\xdc\xb6?'\xcf0\x17\xe6\xa1$NA*\x9cU\xe9sr\xbb\x98O^\x10\x94\x84\x8b\x11\x10\xad\xf7\x89\xd6c`\xd3uX\xb8\xdd\xc7\x86\xb4\x8d\xb7\xed\x1b\xbad\xb1i\x05\xfdt\xa6I\x8b\xbf\x9cw\xf4\xcc\xec\x92\x92\x18?7\x9f!\xfdHk\x90-\xa5\xbd\xdb\xe9\x11\xb6Pp\xe2\r\x16\xc6\xd1\x89\xf6y\xa0|\xd5\xcc\xf9\x99gq\xf3\xb1\xdc\x88kf`f\x8d[\xa8Wx\x8d\xe1\x07\xfdR\xeb>RF(\xd56\x16\xc8\xc4\x9b\x1a/uM\xefe[\x9d\x1b/9\x90\x8cY\xa6\xe1\x04K\xe0:\xd8\xa2r\xde\xc4\x9b\xad\xac\xe6\x9d(\x17\x81\x8f\xc9\x11\xf6.\xb5r\x82\x9f\x83\x827\xc8\xc0\xa0\x9ae8\xb4\xadz\x1d\xe4\x92\xd2\xdb6\xe4,e&\x98\x7f\xa5\x9c\x02\xdd\xb2\xad?\x95iq\x87\xcf+\x10\xfczT\xcb\x90xA\x13Q\x9ar\xa4\x0c{\x02\xb3p\xc25\xf0~\x16\xa4a\xaf\xb91\xd2\x94X\x1a\xbdX\xc4J\xec\x0b.o[\x8a\xd8\x0f`\x97%&\xd8\xd5\xda\xb3\xd0h\x14\xa6\xc9L\xb3\x84w\xe3\xec\xcfV,\x02\x04,,\xbc)\xec\x9d\x9bs\x1cn\x8d\xdb\x8f\x84o\x19\xb53)\xf6\xf2\x97\xb2\xee\xa4\xb6\xb6a\xdf\xa3\xaa\x83\x9f_6q\xec~\x87\xaa1 \xd8\xc5\xe1 {\xfdv4^K\x17\xe1\xb5dg\xa4\xf2\xe9K[\x80)\r\x07\xb9G%\xb7\xcb\xa3\xba[\xbf\xbe\xdfV\xb0\xd7>4\"\xc1\x11ph`[\x1a\xa2\x10\xa0\xb6z\x0e\xbb\xda\xc8\x8e'\xe6\x9f\xa7|\xdc\x1c:1s9\xf8l\xaa`\xecx('\r[ \x1f\xf0\xd7\xa7\xd7\xa1^\x84\xfa\x0cz\xfd^\xae\x8d,\xffub7\x84\xc4\x86\xa3\xea\xc2\x01\xef%\xb5\x84\xadrl\xdd\xdd\x88o ?T&|e\xcf\xbfbI5\x0e\xdcR\x06\x07\x04}\x9c\xb6t\xdcf\xd2\xee\xdfZb\xd7Y\xc0u \xdf\x7f\\\x02\x03@\x18\x01K\x9d\xa6A\xe5!\xb7\x14~\x10\xd1{\xe6,\xbe\xd3\x87u\xd5\xe1/\x07\x197\x01@\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0foCs\x1e\x13}0=\xfa0[\x81h|\xf9\xeaR\xa9\xe3\xf4(\x8c\x018\xaf\xe9\xd0\xa8,\xd4b\xe8A\xa5\xb1q\xc1.+y\xe3\xff\xa8$\x12\xaf\x89\xa7\x9ams\xe6\xcd\xe8\x11u\xff\xe6p\x8a\x8a\xe5O\x08\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f2\x91\x88\xc4\x01\x19\x08/H\x84\xd20_V\xb7\x15\xaf\x90R\x1a\x1b\x16\xcd\x84\xean\xe6\x9a\x89\xc3H\xf0\x9c\xbd\xc3\x95\x18\xf90\xc0\xd2P!fA\xa1\x82\xb6\xa5Wdj\x96\x96\x8c\x1d\x94t\xd6/w\x12K?\xf6\\3\x8c\xa1!\x7f<[\x9d\xcb,\x1fn\xa0\xaa\x8f\xea\t\x90KG\xd0\'\xa7\x9a\x89x\x9e \xf2\x8e\x81\x12\xdd\t\xdf\r\x7fKv\xb5\x89\xa7i\x7fB\x15"\x7f\xe9Y\xa6\xfdY*\x8eX%\xcc\xfcc\x88\xc5d"qH.\xc9\xc8\xe3\xae\xb4\x94\xbdsz\x11\x047\x0c\xf0\x04\x1dWboe\xfeW\x97\xbaD\x81\xa7\x9d\xb4\xfc\x16>\xb5\x05\xed\xd1g\xd5*\xe7\xcf\xd5\xd5\xd4\xc8J\x1f\x859y\xdf\xb7\x1eyu\xc3\xb3\xb4\xca\xa1=8T\xc6B\x17;W\x02\xb9\xdc\xde\xc8\x1f\x88\n\x9b\xb7N\x95%\xce\xc8?\x02t\xfd\xb8\xa2\\\x12\x1d\xd6%7\xe3\xd3l*\x9d\x8f\x93&\xe3?\xc1\xd6\xbe\x14\x8e\xef\x08\xbcM\xb4\xde\xe9\x05\x14)\xa0:W\xebRG\xd7\xde\x1dB\x97Q\xd3\x85\r\xa7\xf0\xf7\xd30\xfcx\xc3ws\x8d\x8e\xf4\x18-3\xc6\xe9\x9f\xe3\x1e\x81\x8a\x99\xdb&6\x8d\xc1\x9d\xc0\x03\xf2\xb7\xbc\xa3\xbd"\xa8\xaf]7\x1a>\x1d\x9cH\xd6\xa8\r!\xa6z\xc0\x117\xb3\x97]PZ\xe8\xdc\xc6\x7f\xf8\x165\xed(\xefQ\xee\x05COb\x15\xbe\x8b\x88\x0fl\xb0WiW\xb1\xffvDdl\xa3\x12\x9cT\\{\xa2\xc3\xad&`\xde\xf0]#\xa3(\xf5\xab\x88\x8ba\x85\x02\xc8\xb3\x1dA\xd20\x0b",\xea\xd3\xc9\xeb?#\x80\xda\xc3\x84\x0fl\xd4\xcc\x1e_m"\xact\x1d\xd2\t:\x1b(\x08\xb6\xed\x92\xe6\xa5\xad\x9b\x84\t@\xa2\x91l\x1a\x90r\x8eTc\x16\xa6\xdd\xfc\xf3#>\x11\xf0\n2,{\x81`\xffa\xf7Jz\x07\x10{\xebh\x90V\xd9j=\xdb"1e\xa2-\xa4\xb4\x82\xc3\xea|\xf8$\x88\x80J/\xa9VU\xbd.\x88\xf7&6\x1d\x18e\xf9\xb7\xb3c\xb2\xe6\x0fvZ\xf4:\n\xb7l\x11\x1f\x00\xcc1\x16\\oQ,\xc4\xd9\xee\xf6\xc4\xf9-\x81n\xf1\xcd\x13DwCg\xbd\xb6\x14\x91\xd92\xb2\xff\x96F&\xc4b\x1el\xb4:\xc5\xbc\xb8\xea@{r\x7f\xf8\x82\xdcgG\xf28f\xc6s\xd5\xa9\x8fH\xe5\x10T{C\xfd\xee\x9b\x1c\x12U\x15 \xf8#\x0f\x95\x85\xcb_\xf5\x1bWO%\x0b\xca\xa1jm\xf2i\xd8\x8e@\xecd`\x93C:\x01w\xbcKrs#\xf5\xd1\x0cp\x1bq\xe3\x95\xf9Q}\xab@F\xb3\xec8*\xfb\x9c\xb9\xa2i\xe4"\xbd\xb1k\x08\xa9\xe0\xe7fH\xf1\xb0-kS\x8bbT\xd4\xe8H\xda\xfb\xe0\x8c\x0b\x8a\x9d\xa4F\x88[G\xe5*\xf6\x84\xb3\xae1\xf6\xc5?\x11Y@|ft\x8d\xa3\x1a\x13~\xd6\x90\xcd\xc8\x97\xaf3\xba\xad\xf6\xdedA\xd3\xae\x08\x00\xf6/s\xd3!dN\xc5\'\xfa\xb6b\x02\xb97\xd2"\x9d\xe6\x9f\x08G\xfb\x05\x1e\xb8,\xe4\xc5\x92\x91\xaaP\xa3\xe4x\x80\xc5\xb0\x14O\x90\x11M\x80\xeb %\xfcs|\xd2\xd5\xf9}\x83\xa6,\x1b\x0bv\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f-r1I\xd9\x9f\xeb2r\xdc\xe0Y\xf8\xe2\xaa\xbb\x94H\xe3e\x89+\xb6\xa4\xca89\x82\x92\x1d\xed\x9e\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f\xe3\xab\xe2\x85P\x08\xd1\xa8\'\x88-\x92e]0\xbf\xa1ai\xa12\xac\xc0hUZ\x82\x98,,\x02d\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f\xad\xf6\\~\xc3{\x8a\\\xc3\xf6@(\x0fN0\x0f\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f\xff\x1dP\x0e\xfeg\xf3D\x9c\xdf\xee\xc2J\xfb\xca\x04\x96\x16\x10\xf10\x17N\x7fL\xf8\x86S|s\x15\n\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f\xf4\xad#UB\x96\xed\xc0qu\x9b\x1cp\x17\x07%\n\x83B\xeb\x81\xabK\x1b\xe59\xa0\x9e\x98\xd73g>\xf0\xfa\xbb\xb7\xbdq\xd1M\x11R\xc3+\x9c\xdaC\xa3H\xeb\'\x04\x0en\r\xf6B\xa5\xb7\xb3\xc5xE\xd8(\xceR"\xc5\x82\x0f\x1f\xa9\x0f\xce\xd9\xd2\x1f\xa5\x8a\xfe\x93\xbc\x02\x18/|\'\\g\xc1\xe0\xf6\xbd\x94\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0fS\xf1\x82\xf9\xdfY\xf3<\xa8\xaf\x18h\xff\xd8\x1b\x19\x19\xcfB\xeb\xe2\xc5k"\x90J4\xe36\x8aI\xe1\xeay\xfa\x1fy\x8a<\xe3\xc4\x8cFIV{\x80\x8f\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f\xf9\x85l\xc3n\x9a=\x9c=\xac\xd0\x9c\x11\x8f\x82\x1cE\xc6\xf3\xe6\xd6\x12j\xfc=al\xed\xbbz\x08\xb5\x13\x9dC\x91ui M\xe2\xbe\xa70\x93\xf7\xa7\xc1Zl5S\x86\x032&k\xd8\xd8\xa7\xdc\xe7\xf3B\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f\xbe\x85\x0cE\x9ep\xc6\x84\x15\xa3\xc4.`\xad\xc9\xb9\x99\x95J\xbd\xd9C\xa5V(\xe9\xcf\x96\x8a\x05@\xcf4dqi\xca\x92\x9f\x1f\x01H\xdb\xfds)A\x94\x9a\x92\xeftq\xa5\xe0\xf9}\x11\xcfkZ\x81tw\x1d%\xc1\x18\x9b\xde\xf3\x88\x18\x88+:\xd7\xd4\xdaW\xf6\xe0\xe1\xcc\xd2\x83a\xea\xdf\xbe\xc6\xee\x82)1\x03\xc3\xb7D\xd2\x8a\x00\x1eO@tVr\xcaO\xadDl \xd7\xa3\xa2\xf4\xda2Q\xce\xaa\x8d\x7f\xd1\xd1\xfb\xc0\xa3>\xb9\xb4\x8eT\xda\xe9z\xd6\xba\xfdT\xb7P-\x02\xa4\xc9\x8a\x1e\x82\xb5\x11\x8e8\xaa\xde/\x84dD\x03\xa6\xf9L\xd7j\x8f%o\xd6{\xf8Gq3(*%\x01\x1d\xea\x8c\xbabe\xe0[^\xa8o_\xee\xa9\tk\xb25\xbb\x07@\x8a\x99\xb9\xbb\xde\xeb{\x92s\xc5z^q\xa9Z:\xc1vtO\x0c7\x9a\x9cf\xdeA@\xb3\xbfX%\x88\x05\x0b;b\x06\x89\x12^,\x82~\x18\x93`\xaeqjy\x1c_\xb6p|\xef\x16>l\x9f\x88\x0fl9\xe9\xed\xcb\x01<\'\x08x\xfa`\xb5\xd4\x14\xab\x10\xb0\xe4\xa2\x8f\x80On\xb7E\xcb\x81\x84\x86\x83\xfe\x15\x8b!Y\xd7\x83*Oh[a\xc1IU\xa4\xb3\x03\xd8,\x7f/\xdd\xed\x8e\xd0\xf2\xbd\x12M\x1eSK\x1d_\x08%\x9b=\xa2\xa1\xeaD\x99mq;HI\xfd.Zq\xec\xa0\x86\x13&\x02\x0bI\xf8\x10\xd6`\xaak\x02\xdf\xe5\xaa\xba&\xfa\xcdP\xde\xe31\x93SN\x0few\xf9\xbf)\x95\x86\xb9~\x83E\xdb\xf2J\x05<-\xddXj\xea\xfeSw\x7f/\x05\xf7)<\x17i6\xb8\xdb3\x13\x8dv\xfd\xa5\xbce\xae\xfd\xc7\xedH\xc9L0@\xd68Z\xce\x1a\x04\x8f\xf8\xeeD`\xad:\x94\xa3\x8c&c[\xc1\x18\xc6s\x7f\x12 \x04\xb5gZ)\xb5\xe9\x8d(\x92\x05\xdag\xa4\x9f\xb8\xcc5\x0f+\xf1\xb9PF\xef\xa0}\xc6B\xea8N\xe8\xb4\xe2\xb1Le\x18\xd7\x18s\xd9m($m\xebM\xf7\xbd1\xac\x8c\x80\xc6\xf8r[\xae\xf0\x16\x88%\x9a\xef\xb2\xe5\x8e\xad\xd0\xc2\x8d\x96\x80\xb6\x00\xd0\x08,\x8c\xe1\r\xc3W\xc0+\xf7\xa5Z\x82\xffi\xad\x01\xe6B\xcd8MN\xb6m\xc6\xa4jS\\\x13\x92\x056\x02\xb3\x98\x8e\x9e\xbbHt\xe3.\x86\x84\xff\x80\xb4\xee\x94?\xbb7\xd7\xc3\xa8KZ\x85Zj\xb7MK\xb3GolC\xba\x128a\xa1a,{P\xfa:\x05L\x16\x0e/\x88l\xcf\xacO\xb7\xd9\x0e\xc7Ur\x9d\xf5d\xc4\xb8\x9a\x82\x18\xdaQ,\x7f9\xc1\x17\xb9\xf4/\x98;U{i\xcc\x83\xe3\xdeuD\xfdU\x06sG\xc7\xeeG\xa2;5\x17\xf0\xf3\x0b\xe8\x01\x97wg(\x14\xa4?\x96t\xa2\xa45\xe3\x1fiAZ\x89O\x19\x06\xdf\xd7W\xc0T\'r\x0f6\xe0\xf9W\xc0\x9aV\xfd\\\x19\xc5yP\x88\xb8pW\xdbU\x98\xa8/\xbb\xb8\xaf\xf8\xe53\r@\xbe\xbc<~\xc8\xff\x11|\x129v\x12\x9c\x8d\x9c\x95#j\x1a\xe9\xaf\xd7\x9b\xd1\x8e\xa12/\x17M\x84\x9c\xcc\x8f\xa9\x14\xec\x86\xcf\x1a\xfd\x1dE\x14]\x9b\x0cc:\xf2\x84D\xaaMiv\x152\xd2\xcbk\x030\x9ajdf\x8c\x06\xecp\xcc3\x92\xaaC\t\x06\xe2RH\xe1v\t\x0fD{@\x04{\xd7\xbd\x8c\xec\xbd\x8e\x16\xbf/@Hrx\xa0E\x16\x907\xaaz\xca\x8fzl\xaah\xb3\xebc\xe9\x7f\xd0\xe7:\x82\xff\xebE\x7fu\xdc\xb5\xf9j\'\x8eI9\n\xae\x98$\xc4\xee\xf5\x80\xbc\xf50O}Z\x0cy\x0f7=\x9cS\xd6\xee\x95\xea\x85T\xe6\x9a*\xcf\x80\xdc\x14v\x8d\x9c\x83\x1f@\xacf\'gi\xb6\xbc\x05~\xe9\xc6\xce\xb2\xd6\xb1\xacy \x13$\xce\xc4\xd1\x02k\x88\xd4\r\xd9A\x9d\x94q\xf2\x06\x15\xdf4\xf1M\xb3\x02\x84\xae\x83}\xdc\xc8\xc3>S\x01\\\x1d\xb0\xfe\x84\xa3s\xa9j\x8a\x13\xd3\xef\x8b\xea\x90x\x87\xb5\xff\xce4\xf9x{\xad\xb8b\xde\xb5\xb5l\xf9\xb3g.\x83\x9dR\xbeD\xd1\x89\xd6+\xe4Xg\x9d\xac\xc4%\xebP \x1f.\xf5\xe78\x05\xefp\x9c\xf3\x0cJ\xb4G\xd4\x1c\x89\x9c\xd3\tj\x97\xcc\xf3\xc6\x85J\xb3\x0f\xaf\xf0\n\xc0@\xe0"\x19\xeb\x81c>]6(c\xcdH\xbb\xb5?R\xd2\xab\'\x01\xc4ug\xf5\xc2\x89CH\xcfK\x8c\xb2\xed\x11\x87_\x16\xff\xc7\xdcwJ\xfe\xea\xee\xc4\x9d\x9f\xb4\xa2:\x01\xd3 \xeb\x95\x84\xadL\xcc\xd9\x12\xa1K\xc7\xc3`&\xba\xdb&\x9f\xf1:f\xe1\x8c\x06\xd1G\x0bw\x84\xaa\xee\x8a?\xcbQ\x8e\x15q\xb7Ey\x8c4\xc3\xb2V\xe5\xc4$\xaf\x05?V\x86\x87\xae\xa2\x96\xa4x\xb2)4\xa5\xe3\x02RZ\xd6_\x8f\xe7U\xe8\x89\xca\x1f\xdd)\x81\x80\xba\xa0\x0c(\xfa\x85\x8a\xac\xa3\x8fH\xb5\xc2\xb8\xd1\x87\x0f\x89[\xa1\x94,\xe4\x05\xc6`\x94W\xc2iS\x01\xa9\xef\xc4=\x92!\rx,\xfeXe\xbb\xb7\n9j \xc4\xaeK\xf0W\xee\nY\xa0q\xd1\xbf\xb99\xc7\x12<\xaa\xca\xfb\xce\x0fCH\xdd\xa7\xb5\r%\xf3\x88\xa7\xd4\xda\xdck\xbe\x186\t\x82\xe8\x99t\xd1\x83\xff\x94+\xa5\xd9\xc0\x8e\xbf\x0c\xf3\xaf\xce\x06K\x86M.\xb8\xaa\x0c\xa5\x0c\xc38\xa8`\x0e\xd9Xq\x10\x007\x99\x81\x9d\xb8O\xeft\xac7\xbcWSN\xaf\xae\x87x\xfb\x82\x18`x\x99\x98\x16\x01AB^\xde\xdf\xa9\xbd{\x93\xdc\xc4\xb8\x9fN\xd5\x8a \x15I\x0c\xcf\n.n\xde\xcbgY\x1b\x1b\xb8$\xb0\xb0\xe4\x13\x1a\x8eN9\xf4Ri\xe3\xdc\x95\xc0\xc8\xc0\xb3\x96\xe2r\x99\xa1\xe9\xfd\xc4\x9e\xfaC\xd3b\x17kT5}\xb1\xbf\xa9\xb3\x03\x186s\xe2\xc7\xc2\xd9\xb25k}\x9fU8\xf9\xa1a\xa0\x994\x029)!\x97\xdf\x87\xda\xcb\x87uO\xfaWTi:\x97$\xfe\xbe/\xb4{\x12\xc3\xa7\n\xe99\x9a,\x08j\x05f\x0f\xd38\xa5\xd9\xc8\x83*k\xc5D\xe3{\x01\xab2\x96\x8c#*\x14|<\xbbFQ\x04\x12\xb6\x1b\xb6\xe3\xf0\xad#\xebg\xf8\xb9\x95\xc1\x98U\xe3u\xa7\x1a|:\xb8\x9d\xa7\x12\xdf\xfc\xa0\x1a\xbb\\\xc8i\x95Zg\xe3Z\xfc\x14?\x17nT\n\x80\xa9Q\xe8A \xfdX\x121E\xd3P\xf4FguK!\x94U\xc6\xda\xed\xd5\x0f\x87\xb9\x7f3\xc3\xd1\x0b\x83c2r6\xed\xa1*\xf8n\x88B\xc4\x94\xbb\x00d\xc1r%6S\xbbq\x02hx\xc1z_p\xd0\x8d\x15\x94\xc0\x90\xa7\x81O\x870ID\xc8\x96\xed\x9cn\xd4\x9d*\x81s\xd3\x89\x8c2<\xad\xac\x0b\x99z\xd8%\x94w\xb0!$N\xe6Gl\xb1k\x87\xf9v\x95e-\x05\x03U$\x1fk\xaf\xc2k\x17\xac_\x0ct\x06\xab\xdd\x040\xc8\xd6O\xd1\xe8\xa2\xf4\xb1\xe0G\x19\x00\x13\x83\x87\xeb\xc7\xd9\xablW\xda\x00\xd4\x9dMmf\xc7Q\xb5\xcf\x1f\x91\x04\x160\xcc\xce{\xd2iw\xed\xcc\x07m\xebc+\x99\x16\x14\x1e\r\x1d\xda,\x98\x16\xdf\xdc\xd4\x92\xd3\xccj5\x80\xf1\xcc\x0f\xf1\xf7C\xe6\x82\xc6\xf5j-\x16\xcc\xfb(#\xe0\'\xb5\xc1\x83\x88\x17\xb2\x9e$\xbd\xa6\x17;\xbd\xf8\xfb\x96\xc4w\x93.QE\xb1E\x97:\x08x\xa04kK\\\xdf\xfe@\x04\x8a\xe9\xfb\xccl\xd6V(\x89\x7f\xde*\xc3\xd9\x92\x8f"\x03\x1b\xea"\xab\x99\x18[G\xc3\x06\x02\xbc\xbbB\xb4,\x05a\x97\x86\x9bw\x91[H\xach#\x01b\x7f\xa5\x7f\xf0{o\x047\x91\x13\xf4\xeb<.,\x9a\xe6\x1f\xb1_\xaf\xd4\x8a\xdbw\xcc\n\xa7|\xc4F\x02\xa5\x8f\x81\xef\x929\xb0\x8c\xea\xfaLw0!\xe8m\xa0L\ne\xfa \xd1\x7f\xcei\x11\x1fc\xfbp\xcbB\xe1\xb5\t\xb2\x02\x83g\xe8` 4zY\xc0zz\xc1\x8d\x83\x0e\x90:r\xafl\x9f\xa5\x95\x1b\x1d-\x98R\xdf\xcfU*\xad\x13\xd28\xa5f\xbci\xa0\xa37}\rpc\x17IC\xa1\r\xda\xae\xd1\x02\xfc\x0fn\x7f&\xd8L\x16\xab\xb8jd\x03i\xf42i\xcd\x17\x85\xf9\xce\xd2\xbe\xae\x9cY\xd8P\xf1\x93\x1c\x06\xc62a\xc2T\x85\x88\xf3w\xfd\xa3\x8d\x82\x94c\xb4\xcaLG\xe5\xb1\x02\xa4S\xbb\xdfC\xe7r\xd7\xe1\xd0\x18\x06\xcecc\x8a\x96\xaf\x1f\xea\xcd\x9bt!\xeaRz\xde\xba\x98\xa7\xae\x01\x9a\xd5\x94\xf7\x07oFI\xe8\x08\xeb\xa7Jm\xf0\xc6\xfd\x9ed\xfb\xdbG\n"\xb5\x93\xf3\\\xa4\xf7\xee^\x8c\xbd\x15\x06e\xda\xbe\xf5\xa1p\x18\x1b6\x914e{\xe2 \xa9\xa2K\x9e\xbc\x7f\xae\\\xceX\xc6_\x0b0s\xb6\xd4\x92\xd9\x85\xfedS\xd4\x03\xafk^FiZ\xeces\xcd\x98\xe1\x11\x9c$\xe1\xcd\x81}\x91\xf9\xd3\x86\x9e\xa78\x00\xa0\x98!\xd7J\x1d\x86\xf4N\x964\x8e\x9f%=\x95\xa3\xd8\xb7z\xfd\xb0\xa5\xc81s\xa1\x9134\x88\xaa\xfb\xb8V*\xe3\xd6\xa7\x9c\x98KK\xdcm\xc5)\xa4\xc0\xc8\x11\xcd\x1e\x19k\x9e\x82\t\x90H\xaf\xde\x08\xbd\xbd\xc0_\x9b\xb2"\x1a\xbd\xd7\x0f\x9d\x1c4\xfa\xa2\xfc\x96\xe0G\xa7\x1a\xc1)\xba=\xcc;_\x84\xcf$\'\x1c9=\xb3\x99\xd1\x061{U\xb8\x1bF5\x9bw!\xec\x8f1\x9c\x8f\xa8\x97\xe9\x08\xc3\x86\xb4\xf0\x98,\xf1\xef\x96R:\xc5\x9c\x91u\xd4_\xc1xy\x1az\xc8\x9a\x10@z\xfe\xaf(c^\xf6\x10B\xc6\xc5-y\x8c\xb2T.\xfe%\x7f\x12iG\xd9q\x97\xf5\xa9\xc8\x0c\x9a(\x1f\xde\xfb\xd9\xdcy\xd8np\xfdt \xd5\xc9Q\xcf\xc3-W\xa9\xeee\xaa\xc3\x17\xd6!\xba\xfaCS\xd2\x84\x86\x0c\xd5QHd@vG\x1d\xd5\xef$q\x85\xfc\xf7\xcb\xca\xe5>V9"PO\xaf]:\xe2\xe4\t;h\xcc\xfe\xd5\x0c\x9d\xbb\xd2\x16\xa1\xa5\x82\x8d{\xac\xefz\xe2\x88\xb6\x19\x8f$\x1eSz\x8c\xe9\xd3b\xc8\x9e\xd15`\x8e\xc3#\xabp\x838\xfc\xf4o\xff.a\xdf\x07\xa8\xa4\xbe\xd3\xd7\x97>=\xc9\xad\xe6\xcbG\t4\xc7\x1f\xd9|\xbc\xe5\xb0\xe2M\x9e*\xfa\xff@0\xe5\xfe\xffU8&\xc5\x0e\x16\xbdS\xc5$\xa7\xe0Z\x89\xaf;\x07\xa2\xf7\xcdB!\x8c\x934\xcf\xf3ez3\x1a\x8b\xe4WT\x9d\x1e\xcc8\xbe\xac\xf2YNJ\x05\x9cd\xdcn\x87J\x93\x94\xe6\x04d\xbd\xec\xa8\xc5\xca\x8a\xbe4\xf4\x0b\xc1\x199Y\xd7\xbdK\xb2\xa3\xe7\xb7\x0e\x03\xdc\x02\x03\x87]\xc1\xb7\x8f\xd9\x1d\xfe\xa1\xda\x1d\x9c\x88`\x14\xba\xcd\xa78\xfb6E\xe2\xabG\x17A,>\x89,\xa8y\xb2\x91\x17\xefcM\xe8x\xb5\xec\xfe2\xca\xcc\xe3\xd3\x7f\xd7\x93"\xd2l\xad\xd7\xc2\xf6.3\x7fJ|\x99\xe5\xabPXMK8\x00Q\xf0\x9a9~\xb6\xfe\x86\xeca"0x\xe3\x86\xe0\xe7\xa4u^\xf3\t\\\xc5^W\xe0\x08\xda:P\x10\xe3\xefc\xcf\x14E\xff\x94\xd4\x08\x0e\xd2\xa7\xe3I[\x99\xfc\\[__\xc1\x84,NB\xf5b?\xec\x01le8\x1a\xd5\xd4X\xa4\xc5\xea\xf2\xb8\xf3\xbe\xd6\xa2\'9x{\xb3\xf6I(<\x0c\xb4\x1a\x10\x14x\xd4\xb1q^\xffm\x12\x88\xea\xfe\xde\xf4\xd4\xd2\xc2Q#\xd23[\xc45\x8a\xa1n9\x8c1\x16vJ\x1b\xcb\x91D\xfdd\xbb\xa6\xcb\nV\xebU\x8d\xea\x94\x91\xf7\x9d\xe6\x9f\x13\xc1\xb8\x1e\xbc\x1e\x8e+;\x87\x9a\xd82\xf8\xc4\xadi\x08\xf9\x10\xd3\x9c\x89\x03\xa8\x96\xff-\x85\x81\xf4e/r`cT_\x97\xb6F\xb5\xb7|\xe0\x16a6/AK\x81\xfe${\xab\t4\xcd\xa0@\x0e\xb1\xb1\x05\xa2\x88\x14"\xe3\xccEb\xd24\xc5\x9f\xeb6\xf4&l\xbf\x9e\xc1r\xf8j#\xa7\x87\xcf\xd2\n\x997\xe5\rhG\xacMRG\x00S\x15hC\x12\x9f\x9b\xf8\xd9\xf9_x\xaa\xb5A\xb9\x84\n:\xc8*o\xff\x0b\xf0\xee\xb4\xe8\xe4B\xcb\xbb\xdbF1\xd0:\xaa\x13\xb9\x9d\x98\x85\xe5\x8bl\xa3\xb6\xd1\x97m\x81\x17\xf0ce\x81@%1\xcc\xefqV\x81\xa6\x81\xcaC\xbb\xdcy\xaea\x0e\x99\x14\xc2\x8f\xd8nT\xc0q\xcf\x98S\x0e\x0bd\x87n\x88\xf8\xa1\xc0\xb60X5\xec`\x04\x01\xc8s$\xb4\xb0F\xad\xc7K\xfb\xec\xc3\r\x86D2\x07\xd1\xc9\x94\xa7\xe4N\xd4\xd7\x14\xfc\x9f{\xd1=\x94V\xc2|\xedb\xfd\x91\x87\x08\xa2kD\xe5\x8c(\xad\xf7E\x15\xd3v\xaa)\'\r\xc2r\x93\xf0Z\xb8\xbe\xbb\xd4\x0e\xa7\x11\x13\xfc\xaaG\xd2M\x05\x93\x1b\xbd:\x01\x0eS13<#\x83\x8ae\x1e\x82f<\x0feg \xae:Z\xf8M\x8f\xa9|\xa0&\xbd\x1f\xe38O\xbe=\xcf\x9fPB\x95\x1cv\x1a\x9aA\x08\xd9\xba\xb9\xd6\xf6eA"\xd4\xdf\xbdN\xfdX\xd5\x1b\x07\x141\xe5\xa8\xbf\x88"\xcfp[r\x9d\xc2m\x87\x0fo\x1bl\xef\xd7\xd1\xc0\xeeH\xb4\xa2\xca\xc9{\xb8\xe8\xa2]95\x89\xfa\xebx\xceQ\xb1\xba\xe6\xa4' # noqa: E501 - with open(self.location / chest_id, "rb") as f: - data = f.read()[8:] # Strip magic bytes - return xor(data, key) + chest_file = self.location / chest_id + + data = read.contents(chest_file, filetype="malicious") + if data is None: + return b"" + + return xor(data, key) def parse_from_log(self, _=None) -> dict[str, QuarEntry]: - self._initDB() + logging.info("Parsing from log in %s", self.name) + if not self._initDB(): + return {} quarfiles = {} # Return the value of a field 'f' + @log_fn def get(e: ET, f) -> str: return e.find(f).text - for e in self.root.findall("ChestEntry"): + for idx, e in enumerate(self.root.findall("ChestEntry")): + logging.debug("Parsing entry, idx %s", idx) chest_id = get(e, "ChestId") path = get(e, "OrigFolder") + "\\" + get(e, "OrigFileName") # Check if an entry is in the vault.db @@ -88,24 +156,32 @@ def get(e: ET, f) -> str: def parse_from_fs( self, data: dict[str, QuarEntry] | None = None ) -> dict[str, QuarEntry]: + logging.info("Parsing from filesystem in %s", self.name) quarfiles = {} # iterating over bigger files, which were not logged to vault.db - for entry in self.location.glob("*"): + for idx, entry in enumerate(self.location.glob("*")): + logging.debug('Parsing entry, idx %s, path "%s"', idx, entry) chest_id = entry.name if not entry.is_file(): + logging.debug("Entry (idx %s) is not a file, skipping", idx) continue if chest_id == "index.xml": + logging.debug("Entry (idx %s) is index.xml itself, skipping", idx) continue if chest_id in data: + logging.debug("Entry (idx %s) already found, skipping", idx) continue malfile = self._getRawFromFile(chest_id) - entry_stat = entry.stat() + entry_stat = parse(self).entry_stat(entry) + if entry_stat is None: + logging.debug('Skipping entry idx %s, path "%s"', idx, entry) + continue timestamp = DTC.get_dt_from_stat(entry_stat) size = entry_stat.st_size From ba8c90e071bfa97e91f4b12817db4eb76db978b8 Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Mon, 14 Apr 2025 00:14:44 +0200 Subject: [PATCH 19/40] Add new logging techniques to AVG --- maldump/parsers/avg_parser.py | 112 ++++++++++++++++++++++++++++------ 1 file changed, 94 insertions(+), 18 deletions(-) diff --git a/maldump/parsers/avg_parser.py b/maldump/parsers/avg_parser.py index 9911d2f..0358b11 100644 --- a/maldump/parsers/avg_parser.py +++ b/maldump/parsers/avg_parser.py @@ -1,45 +1,100 @@ from __future__ import annotations +import logging import sqlite3 import tempfile from datetime import datetime as dt from os import unlink +from xml.etree.ElementTree import ParseError, Element import defusedxml.ElementTree as ET from maldump.constants import ThreatMetadata from maldump.structures import Parser, QuarEntry from maldump.utils import DatetimeConverter as DTC +from maldump.utils import Parser as parse +from maldump.utils import Reader as read from maldump.utils import xor +def log_fn(func): + def wrapper(*args, **kwargs): + logging.debug( + "Calling function: %s, arguments: %s, keyword arguments: %s", + func.__name__, + tuple( + ( + arg + if type(arg) not in {bytes, AVGParser, Element} + else "<" + type(arg).__name__ + ">" + ) + for arg in args + ), + kwargs, + ) + return func(*args, **kwargs) + + return wrapper + + class AVGParser(Parser): + + def __init__(self): + self.db = None + self.tmpfile = None + # Cleanup + @log_fn def __del__(self): if hasattr(self, "db"): self.db.close() unlink(self.tmpfile) - def _initDB(self): + @log_fn + def _initDB(self) -> bool: # Parse index.xml - self.root = ET.parse(self.location / "index.xml").getroot() + try: + logging.debug( + 'Trying to parse index.xml file "%s"', self.location / "index.xml" + ) + self.root = ET.parse(self.location / "index.xml").getroot() + except ParseError as e: + logging.exception("Cannot open and parse index.xml", exc_info=e) + return False # Decrypt vault.db and prepare db connection self.tmpfile = tempfile.mkdtemp() + "/decrypted.db" - with open(self.tmpfile, "wb") as f: - f.write(self._decryptVault("$AV_AVG/$VAULT/vault.db")) + try: + logging.debug('Trying to open temporary database file "%s"', self.tmpfile) + with open(self.tmpfile, "wb") as f: + f.write(self._decryptVault("$AV_AVG/$VAULT/vault.db")) + except OSError as e: + logging.exception("Cannot open nor write temporary file", exc_info=e) + return False + + try: + logging.debug( + 'Trying to connect to SQLite3 chest database "%s"', self.tmpfile + ) self.db = sqlite3.connect(self.tmpfile) except sqlite3.Error as e: + logging.exception("Cannot connect to SQLite3 chest database", exc_info=e) print("AVG DB Error: " + str(e)) + return False + return True + + @log_fn def _decryptVault(self, vault): key = b"\x92\xaa\xbc\x89\xef_\x1b\t\xaa\xad5\xf8\xadg\xe9+^Z\xfe\xdd\nt\xf8\xfb\xc3\xa5\x1e\xad\x87\x00\x9e\x16\x82\xec\xdb9(;w\x10\x16\x17\t\xdd\xef\x898\x8c\xff\xbbV\xf7\xa4\x01JU\xd7\xd6\xe2b\xda\x14*\x9c\x8a\x88\xe1\x8a\xb1\x8c5E\xbaZ\xa1\xae}6\x02ac\xa3\xf2`\xaa8\xf1~vv\x07\x1a\xd4\xc2I\xd4(e$\x98\xcf|\xf2\xbd\xc9\x92\x88\xce\x82\xdc\xc9q(i\x9e A\xb8\xea\xf7,\xb9\x9cRbm6\x96fY'\x90\n\xf9\xb5\x9a\x94\xcf\x9e\x96R\xb0\xeb\xdd&f\t\xe0\xe9Ls4\xc5Q\xb6\x1e\xdeHS\x01\xff\x89\xb2]\x93\x08J\xe0\x06\"e\x96\xefg\x8d\x89>\x86^\xd5\xcf\x03(\x08\x9c\xa0(\x8a\xd2\x07k\xc1\x81\xe9\x1a\xd9\xe5\xf3$g<\xf2nR\x13,,G\x07]K\x8dGOKn\xb2\x93\x13ZHR2\x08\x8cu\xac&t\xb3\x08\xba\xfci\xde\xcf\xeb?\xd9\xa0\x97c\xaa\xf8,)\x8b\xe9w\x854o\xa0\xa2U\xb1\x16F\xe6\x13\xda\xa9@\x87\xe0m\xdb\xdb\xef\xb2\x8cy\xa4\xfadX\xddH\xec\x97\x91\xf5\x05\xc5\xa4\xf4&63\xd6\xe8\xa1\x12\xd5\xe7\xb5%\x15k\x16\x05%\x0eZ\x17\x9e\xe2\xb1\"\x1e\"\xc0\x02\xa4\xfb\x1b%{-TI\x8a#\xd2\xdcO\xd5]\x9c\xa3j22\xb8\x01\n\x1f%m~o\xa3TW\xbb\xe8\x14?\xdf\xc2[\x81^\xd4\t\xd4\xb8\xb5\x9dX.\xd4\xf2\x18v\x13E\x88\xacU\xf2\x91\xa9\x0e'\xf2\xee_\xd1\xdb\x95\xbb\x8b\xb5b\x1d\xcb\xef\xf0\n\x01r\xb8D\x82\x84\x18S\x12\rL|\\Vz\x9c\"G4Y\xee\xa4g\xff\x1e\xec\xb2]\"\x04H\x07.P\x83\xd1\xd4\xbfZ\xb6\x0fa\xf28\xe4\xdc\xed\x18\x82\xdf\xae\x90\xef\xfd\xb3>T*\xcf\xf0\xb4{\xbf_8Bg#I\x1f&\xfe*]5\xcf\x1f\xbd\xee\xca6\x80#u\xae\xc6\xb3\xfbp\xb3\x9e\x80\xec\xb2\x8eB0\xb0\x13?\xab\x0e\xad\x0b\x91{\x16\xfd\xa4p\x92~NYK(\x1e\xb9WlW\x1e\x8d\x0c\xa1\xc9d\xd0\xb84\x13\x95\xd0acjP\x96Jf0\x15 \x17\xe1\x08\x06\x0e\x1f\xa0k\x89 \xfe,\xc2\xf1\x14\xfb\xbe:s&\x82E\x15\x80\xb7t\xa3R+\xb2'\x06\x89\xffZ\x80\x14\x98\xff\xe5\xac{\xc3^\xb3\x8d\xa5\x14\xf0\x08s\xd1!w{\x08\tl]\xe4\xc3Ys\xaan+\x1d\x19\xa9\x86M\xd5\xca\x87\xb5\xb4\x13\xf2\x06\x15\xfdKy\xba\x03 \xe1\t]\x0eyS\xc6o*[\xf5\x92JE\x0c\xc6\xa4\xd8\xa3\xb2@\xe1\x05\xf2\xd2\x9d\x9a7\x98wC\x93\x053\xae\xc4mL\xb3e\xe2\xb0\x9f\xcdE9O\xd3x+\xd4h\x9a\x159\x1ak1\xf4\xb5\xddc\xda\xb8~N\x0801P.\xb3D4C\x84<,\x99&\xf48n\xe5\xb7\xb4\x9fP\x10\x02\xb7\xc6P%v\x19\xb6\xa1\xe1\"\xfc]\xfap\x81\xa1\xa8\xc8\\\xc5\x00\x03\xc6)K\xae\xac\xd0\x15\xff\"cj\xc2vTW\x99U\x97\x7f\x88\xa2\xbd3\x87)\x84\xa2\x07M+a\xe5x\xcb\xcb\x13w\x15\xf7\xbeRe\xbe\x9eVg\xd2\xf6\xd2\t\xbb\xc7\xed\x98xW\xb0\x87Z\xf8\xf84\xe8\x87\x10\xcfv\x89;\x8c \xddJrJ\xd1u\xdd\x85S\x8b\x96\xc1\x03\x97]=E\x01\xbc\x93\xa4*\xfe8\n\n\x1d\xc9S\xee\xdcm\xdc3\xe2\xaf\xcc\xb0\xa2\xea[\x1a\x0e>\x1e5SEkM\xee\xca6\x10<\x18\xf0\xbaZ\xa3sy\xdf\xcf\x13D\xac\xbc_-\x0bc}\x87\x8cZ\x8b\x83\x8cw\xc8@%\xb1\x84u\x1d\xcb\x8eE\xe8\x82\x92*\x1e^\xf0\x99N\xce~,e\xf9v\xfc\xa7\x8c{Oc\x08c\x1aFH\xbe@\nr\x7f.\xe6\xfb\n\xfb@\xd7\"\x92\x15]\x00\x8aV\xdb\x01\xa6)3\xee\xcb\xf3O\x91\x9c\x1a\xe3\xbcD\xcdTG\xd0\xfe4\xf0XbX\xfa\x18\x1e\xe8\x01c\xff\xa2~)\xa1\x1cJ\x80T\xbd!x#\xba>w\x07>\x95\x92q\xa4\xd4\xab\xad\x8e\x1c\x87t>\x10\x03\xb1?H\x08\xafx7\x07|H\xfd\xa8\xf6y%\xe6Mp\xe1tIC\xaeJ\xb6\x14\xed\x1b[\xa5\x9b@\x04\xc7zu\xb0\x11\xb6\xaf\x1e\x0f)\x96\x00\xd9\xe5\x8c\x95{\xb5\x11\x02\xf3\xe0m\xc4U\xfc\xc5\x11\xb4\x89\xb4\"\xff\xbb'\xb8a\xf8\xaf\xbf\xea8\xebvG\x1d\x10qq\n\xdd\x9d\xdc\xf51\x0c\x91\x0e\xc0d\x0eUf\x88\x12;\x1fY\x89Kf\xc9\x9c\xbe'YuM\x18v\t;C:4z\xcb;\xeb\x01j\xda\xf8\xa2d\x18\\Y\x92\x0c\x86@\x1a,\xe3\x1e\x14\x96y\x08\x95\xe6RmP\xffT\xb8\x12\xd1\x82f\x80\xfd\xdb!\xd8nky\xe5\xdb^y\xa6`\xea\xe8\xbe\xcc\x91\xab\xb8\rVG\xa7d\xef6k\xb0L\xa2\xe8\xc4^F!\xfc\xcbc\x00X\x01\xcd\xf5*:\x1a#ck\xba\x9b\xdb4\xc9`@\x00;\xdaJ\x15WM\xa9\xec\xa9\xaa\x97\xea\xb0\x044\xb7\xc4*}\xc4y\xfa\xe4\x86\xbe\x83_\xac\xf5>B/s\xa5\xea\x8a?!KhY?\xb2\x18]j\x02+\x93V\xe5\xe9\x9b\x92\xf1-\xcaL\x94\x87\x12\xd3\x9e;\xb3\xa0\xc1 \xb9\n\xa9\x00\xf0\xd0\xc9\xa2\x8fj\x04\xa5\x02R\xf3\xb3\xbd\xe2E\xc5F+\x89'\x1c\x81\xd9&4\xd0Fn\xa6\x16\xa8\xc0\x99a\x15\xb8\xd9\xe5\xf6\x91\xe6\xfcb\xef\xac\xcc\xf3\xf1\xef\xa3\x04\xcc\x867\xc3\x8d\x1c\xc5h\xb8\xf94\x81\x07\xe3B\x0c\xdd\x82L<\x97\xa5\x92\xd3\x0b\x8b\xff\xa2]m\xaa\xc1\x1f\x94o\xf7{\xbaI]\x8a\xf57B\x85M#\x9c\xb1w+\xbd\x95\"\xd9\xe8I%\xe5\x19!\xdbY\xf2\xd6\xf6\xcap\x10\xa9\x1e|*\x96\x7f\x87\x18 Vs\x99g\x19\\\x08(\xc9\xa7\xa7\xafj{d\xcb\x9ap\x87\x13\xa7\xd3\r\xf0Z\x11\x8c\x8e\xf0\x94\x9d\x9c\xcb\x89u\xe7M\xed%\xa12\\\x1b\xaa\xccO\x0f\xaek\xc9\xfb\x0fP\xe4\x02\xd4 d\xf2\xa6\xec\xf2\xb3\x10\x91\xad\x91\x88\xdaaW_E\x10\xb3\x9b\xbc\xd2U\x849\xdc\xb5K\"\xe0\x12\x90u\x9b\xf0o\x9d\xef)1\xf7-V%(\x05\xc3\xfc>\xe9\x8e\xb0\xf4r\xf9\x1b)>5\xd6l\xaa\xa3\x8dg\x14N\x89a\xfbW<\x9bw'\xac|$P<\x8a\xf6\xdf\xce\x97\x816L\xb6+\x83\x80\x01\x07\x98C<\xc5\xefo\x8fi\xd02\xe2fb\x9e\x08\xdb\xaa\xbd\x9ba'&\x81:2\xc4\xe8\xbe\x1c\xc2\x02\xd8\xc4\xf8\xd16d\x82\x00\x1e\x03l\xf1)\x90\xda\x8c\xe9\x93\x91\xc1\xb8\xf7\xd6\xf5*\xc3\xf5#\x93W\x9d\xf1\x97\xa7\x87\x06k\xbf\xa4j\xe7a\x13iW\xd6\x9b\xbf!:\x1e\xfc\xd7:\x92\xba\x05\xc6\xa2L\xfd\xcfv\xce\xd2\xbe\x99\xc9,\xf2\x02\xa2hB\xa1\x14\xa1\xd7N\xa7\x90\xd4~\xac\x83_uz\xb0C\x9ff\x00[;2Hj\x0f\x96\x16\xe6I\xca~\xa5\x1e\xeas\x9bz\xe7!QMZZ\xfc\x01n\xdfl\xd3\x06\xf4z\x08\x0b\xe0\xd9Y\x02\xef\x98\x89\xa8\xcc\xbe\x17\xab\x08\x89Z7{\xa0nY6\x93\xa1\x12f\x8ac\xb1\xb0'\xac\xa2o\xdf\xf9}\xe4\xf8\xae\xda\xf2\xdb0*q\xd8\x87\xd2`\\U\x9bj\xd3\xcb\xec\nG\xb2U\xe0q\xe2\x85\xbc\xaa\xe4f\x0b\xaf\x00\xb7\xac\xc1}ez\xb5\x95B\x91\xdbT@\xd5K\xca\xc293\xa2\xceB\"\xa3\x83\xf9\xebn\x8f\x936\xfc\r}\xac\x00\xac{4\x1b\xceyN\xf3\xa7s\x06~\x12\x0e\x12l\xd3?\xd5\xb4\xc5aw\"[ \xa3\xc4\xc9J\xd0i\xf6\x0fe\xef\xdb\xe2\x9c\xd6%2%?Zq\x0c\xe3\xa3F\x0b(\xc8\xd1\x92\x9b\x1a\x06\xc9z\x12o\xde\x075\xd4\x1e4\xfe\xe3\xf7\t\xf5\xabtPu\x8bxwF\xbba\x8aX\xd0w\x82\xfa\nT?\x03@\x16\xc3>\xdf>\x82\xc9\xdc\x1a\xcf\x7f\xa3\x14\x83N\x95z\x1a\x1e\x1a\xd5f0\xc8\xf2z\xad1?[?Jj\xc8&q7X\x10\xc7w#R\x87\x81\xb2k\xcb\x19LNrq\xc7I7\xfb\xb0\x818\x14x.\xa6\xdcZ!\xe4\x8a\xad\xa7 \x81\xec\x0e\x85\xca\x86\xdd\xe9D\xc6\x1b&M\xeeW{[X\x87\x1d\t\xdcK \xd7\xfd\xceN9\xf5x\x17&\xd1\xa9\xe3q65\x84\x03\xbe\xc8\x19\x91\x9e\xbb(r\xe3h\xe1\xad\xb8\r\xf2\x8d\n\xe7t\xb9y\xf5\xf5\x1fq\x95\x97,\xe6\xe4\xbciQ\xdc\xab\xe2\x87)mh\xb3\xf7)\x82\xb5\xd9\x0c\xfeE\xff\x8f\xdc\x96\xb4\xca\xf1o\\\x19-\xd3\xbfa\x8b\x87\xaf\xd3\x05\xd18\\j\xa5\xd1\x87G\xd4\xe5\xc9\xd8)u\xf0o\x86\xfaQ\xad\x94\xcfK%\x1a:\"o\xcd<\x89b\x16\xd5\xf8\xd6r\xb2\xcdHO\x04[~\x14\xbf\xaa\xf1\xb4T\x8cu\x13\xf9\xf5\xd5\xec7\xa9*\xec\xc2v%\xbb\x98\x96\xb3\xc3f\xeee1\xd1\x7f?\xc0YwD\x04yn&\x92\x01\xd7M\nE\x88'\x08t\xd6\xde\xdeF\xcc\xf0pS\x153}Ut3 \x80\xb6m\xe8\x89\xdf\xcb\xb9h\xe268\x0f\xfb!~\xbaE}>o\xf6p>\xc3\xd5\xf7\xee\xa8\n\xf2\x8c\x81=P\x0f\x1a\xd5\x17\xd9\x16\x19\xb7\xfbi%(\x11\xd1t\xf2/\x90\x91PR$\xd7k,\xb2HE\x1c\x0ek\xe4\xa4\xe6\xc9\x8a\xb0Y\xa3\xa7\x1d=\x01\xe5\x00\xb6n\xa6\xd7A}9(D\xbd\xb5TJ.\x9d\xa2\xac\xc0\x91\xd1\x0bQ-,\x89\x15m,g\xde\x0e\xd9\x11Pa\xc5\xfc\xb7\tRY\xe5\x94\xc1\x01/\xe4\x92x\x1f\xfa%s\xd3\r\xb5\xb2O\x97x\xb0\xb6(\xa5R\x1a\xa7\xa2\xd4\xcd\x99\xfe\x05l\x7fh\xfa\xc7\xcc)\xfc\x1ee\xbe\xf7\xcc\xdb\xc2\xddg\xe1\x9cUL\xd7\xb4\x8e[+.\x03(\x19\xc8\xb6\xfd\xec:\xab6?^H\x04\xbdc\xb2\xa4O\x0bo\xc0(\x19%h\xc1\x87\xf2X\xa2\x05|>\x1fh\xcd\xa0\xd0_\x9f\x88\xfd\xbf\xb8\xd2I\xf1\xaf\xf4\x0c\xb2\x96\x1eq\xd0ss\x11\xf8\xf0\x06\x18\x97\xb5\xb2\x92g\xe7\xe5J{n1\xedUo\xb1\xd9C\xa1/\x8b\xe8R+\x167?\xf5\n\xdd\xac\xf2&\xd7\x07\xf6Nd\xe8U\xea\xecq\x7f\x85\x1a\xbd\xed@\x7fL\xfc\xe8\x9c\x18+\xb8X\xf1\x7f\xee[\x88x\x91\xcd\t\x15N\x16\x98?9\xdf\xd06\xb3\xee\x99\xaf\xddw\x00*\xbd\xd9\xaeQ\x04\xd8S\xd2\xbb\x0e\xa5\xf7\x06%w\xd9\x191\xe2\\\xdb%\x8f\xf7\x9b\xe0\x98\xf5\x1fx0-\x9d\xcb\x8f\xfe\xe0p\xfc\xed\xf1\xa4\x98\xacr|3\x82\xf0\xf8\xfd\x94\xb6\x8a\x14\xe5\xf2\x06\xaf\xee\x9e?\xcc\x10\xbf\xe0\x83\xcb\xdc\x7f\xcf\xc5\x13\xe2\x9e(G\x8a\xae\x84\xf9sJ_ \xbf\r5\xde6\xbf4\xa1\np\x9eC\x8b\xb1l\xa3\xa0PFI\xc0\xac0c\x9f\x08\xc7\x8b^\x1e/9\x95\xda\x8a\x8f \xe1 T2{^\x8e\xa0\xee\x0fc\x88\x82\x82\xafM\xc6\x05%I\xbf\xedb\xaeD\xf8\xfc}\xbb\xd2npd\xd8q\xde\xd6\x06\xf4Q\x80g\x8b6\x92\x8d4\x06'E\"\xa0b\xbc\xde\xc4\xa3#\x9eu\xdeR\x9b\x9aR\xc2\xcb\x04t\xd3\xf9pu\xe8\xb1f\xd4\x8f\x91\xdd\x9e\t\xab\xaa\x10E\xd6\xb4\xec\xfe\xca1\xcfnw.\xcbR\x80\x817\x12\x075X\xdf\xd5h\xc5Q\x1b\xcei\xc4-e\x16D\xfb\xfb]\x06\x7flz\xd8k\xdf\xb0\xd2\x910\x83\tr\xbaa\xee0\xe8V\x84\x03\xf7\x91H\xd5\x82\x9b5Q\xdbM\xb1\xaf\x07\xf0h\xba:\xbf\xd0zAr\xc8u\xaf\ta\x85\x83\xfc=\xa0\xb4\x99\xd0}0NxS\x16:\x15)\x1a\x80\xfc\xf5vf\xc8|\xff4\x8ekw2A.N\xfa\xd6\xd6\x1d\x93\xfc\x7f]'\xb2G\x84pBX\t4\x1e\xbdI\x84\xc5\x8a\t\x1e'W\xd7\xdc\xb2\xb3\x9aJ\x11\x83\xb9\xf1\t(]Z\xc2\xf0N\n\xb4\xeag\xefY+\xcc\x08\xa5\x07\xd3Z3?:\x9d\x96@\x7f\x9d\xc3p<_AD$\xbb\x8d\x1a\xc6=u\xab\xe6\xde\xc2\r\xf0@\r\x1d`?\xc1;\x98\xce\xef~z&\xc2r\xdeg\xaeH \x82\x91s\xfd\xdba\xd9\x1a\xad@\xc9\x01l\xd9w\x81\xb5\xd2\xe3\xc7:\xf1;\xbf4w;\x15\xf4\xe5\x9d\x0f\xe9\x94y\xaa\xa5\x04\x91m\xaf*&\xfd\xea\xe23k\xdd\xc4O%\x18)&~\xd9\xd2\x91\xd3\xc3\xb6\xd7S\xc1\x12\xdfm\x08\x8c\xcb8<\xe27\xfae\xb5B\xbbz\x8aL\xa7\xde2\x89\xc8^\x05\t\x92\x91\x0bp\x14R9Go\xa9v\x05q\xa5\xf8\xb4\"\xa0\xe8S\xfa\xba\xce\x87\xe1q\xccu\xf4S?\xdd\xc7\xc6v\x8d\xbc\x7f`\x04\xbc2\xd9C>8%.\xfb\x951\x17\xdf\xeb\x04![+W2V\xa8\x07]\x8c\xff0\x15O\xe2!AA<\xa5\x87\x06\xbe'p\x8ch\x05HA\x11u\x990\xcf\x96\x8c\xa2\xa3\x9a\x7f\x8a\x08\x0b9\xe2\x19-.\xc83?\xa7\xba\xe5\xc3\xeb\x7f.\x04=\r(FO\x08\xa0\xeae\xc6\xbbCMsP'&Iq\xf9(\xaf\x00\xa1+\x17N\xd1\xad\x0fV9Lp\xdc\x81\xc4\x04\xd1\xc7^1~\xf1\xcb\n\x95\x9bb\x1c\xcdj\xcdm2R\xdb\xe7\xf2\xfeB>9\xd6$\xb7\xeb\\\xbd\xa6\xd4\x0e\x04\xce\xb9\xad\xeeiqz\x8d\xcb\xceJ\xeb9o\xb8\xfa\xd6w\x82\xb2\xdd\\\x13\xdd3\x14`h\xd4\xfe\x1c\x9c\xded\xff\xfe\xc4^\x99]\x10\xfbq\xe6\xd6\xcf\x19gq\x80\x93\x84Ms\xa0\x1c$\xd1l\x8b(\x04\xbf\xcf\xf3\x8b\x08tV\xeb\xa9\xfe\xaeMDh\x1d\x9a\x84\xca*\xb1o\xb7\x81A\x9aj\x96\xf9\xfa6\xfak\x8b\x97\xdb\x1e\x8f\x94\xd7\x1a\x7f\xb7O\x1c\x97E@\nT}I\xdb\xbc\x95}j\t\xe0\xd3\xb9\x03x\x87g+\xb0\xf9P]\x01\x19\xd9\x95\xe6\x877\xd5\xcb`\x81\x12\xfc4\xd3\x9c\x08\xbf\xbd\xff\x18\xb0\xf5\xadG\xe4\x94\xd6\xde\xa2\xd3R\xd7-t\\#\xf8s\x14\xbd\xe6s\x12\xcfk\x0c\xfcq\xbb0\xbc\xf5S\xd2\x95R\x08$\xc6\x97w\x08\xee\x00{\xfdd]\x13UV\xe2\xce\x9a,2\xdb=\x04\x9bg\"\x9b\xea*\x8d\x03\xfdT\x1c\xc8\x8aI\x80\x12\xbc\xa6O\x93\x93\xf5\xaa\xfe\xa8\xd0\x8c\x13\xbfy\xba\xacw]\xaf\xd2\x07\xdc\x97\x86II\x9a\xc1\x08A\t\xaa\x0f\t\xd1\x04+\x8a\xe5\n.\x90\xc2\xc2\xdc\xe7\x9b\xb6\xe3\x1e'\xadc\xe0\xfdx\xec\xee\n\n\xb6\xf2\xdeEC\x18\x95\xe9\xfe\xff\xc0\x1d\xbaG\xdf}&_\x96V%W\xccY\x169o\x9a\xca\x0b\xa3\xf1\x19\x05\x8e\x1b\xbd\x90T\xb8\xc7\x13_3\x1dx;\xcd\xe2\xcd\xc4\xeb\x00/;j B\tf[*\xa2\xc3\xb7M\xa7rs\xd3\x8fc\xa2\xfa%\x05\xe2\xc7\xc4e\x07PoM\xbe\xd4\xa1\xf8G\x98(\xa6\x8b\xcc\xb4i\xbdm=\xdb\xb1\r;\x10bf\x1c\xd9o\x97\xd9\xd1\x01\xa0 #a\x17\xa2\xb4x:p\xf71\x93\x12\r}\x98e\xecq\xb2\x81\xf1o+z\x0f\x9f\xe0\x17\xcf\x940\x84S\x87\xc9\xa0\x05~v\xa92\x18y\xfa\xc7\xea\xc8A%<)\xa8Qo\xc4\xfc\x14\x96\xa2\x85Oq\x86;\x05\xf6\x8f\xab\x16\xf8Dy.@ \xa7\xfah\x1a\t\x02\x82\x01\xdeF\xdb\xac\x19\x0e\xf1\x982:\x883\xf9\xf4\xcb\xe5u\x0f\xa61.\x81\x11\n\x96\x97QK\xfa\x80\rGg\xf8\x80\xdd%\xf0\xb7\x84\x83\x1c\xe8\xf5\xe9\x87\x82aO\x80\xb1?\x9cMu\r\x02\xe17\xa6>p\xe5\x01!\xe9MXi\xa0R\xd9^\x90b\xacm\xc3\x07\xc0]G\xf6\xb3\xfc\x98A\xf3j#x\xd1Z0\xfe8(\xcc(}\xdep\xe4\xbb\x83\r\xd2\xb2\xb4\x0899H\xbc\xbc\xc5g\xb8\x03\xac\xfd\xd3\x07\x15\xf6\x15\xda \x16\\k\r9\xdf\xfe\xac\xf6h\xee\x01$\x89\xca\xb6\xefXpP`c`\xe9@\x94\x80\x10\x1a\xc3\x0f\x94Z\xdd\xff\x8b\xef\xebP\x1dj\x8aE\x7f\xcc4\xf1AbW\x92\x9d\x83Z\xd6\x80\xf7T\x85\n.\xe4\x0b\xd8\x8c\xae\xa4\xdd\x11P\xd2\x93w\x87\xdc\xa4\x00q\x02\xbfiD\xab\"\x80\xd0\xef\xb6\xd70\x1e\x00\xd5\x95\xb4f\x9d\xe4\x10\xfd\xf7o\xe4\x9aGU(\xf6~+\xd6\x17\xb0\x0ejF\x88n2\xd1\xdf5T\xc5.\xd0\xc6\xa5\xd5\xbb\xf3e\x86R\xe1\x8bX\xb7\xd3q\x13\xf3\xbb\xebM\xd2\xa0Y\x1dfG\xf0\xd5\\\xa1b\xcc'W$\xad\xa8>0\n\x07\xa8!Rk\xd5\xdd\x1d\xd0\xf4\xcf\x98\xa1r>}\x95UP/|f\xc7p\x0c\xd4\x17VAWf\x13`\x9e1\xa3\xadA\xb0\x8f)\xf8\x1c\x04\xfbQ\x95\x8c9_y\xe5\xe5\xc7\x06\xa7}R\xf9\xbbO\xe9}X\xeb\x98t\x8b\x19\x94\r\xdd\x1a\xbc\xfb\x01\x9bc\x96\xfe\xbc\x85 \xba\x11\xc8Gw\xae\xfb(\x0fs6\xe0zb=\xedo\x02\x84'S\x8c\x96\xdbH\xa1}\xe3h\xb8z\x08\xbb\xef\x1b\x98\xe8\xafY\x8b\xcb]\xa4\x14\xb8\xef\x90\x0b\xd9-\xadA\x04\x99P\xc3s\xc1\r6\xf3\xb5\xff\xf57z\x94\x1b&\xc07n\x83\x82\xe1\xa5\xe9\x8a-\xfb\xc92}\xba<\x83\x97\x05\x9d\x08\xcb\xe5\x12fdM7\x96Gm\xaaT\x9e\x0b\x80\xff6q\x0fAf\x10w\"9\xac\x81z\xac\x98\x19\xfb\x07sX\xaa\xf3\x08n\x11\xd6\xdc\x1c\xe6\tM@\xb4\xf7\x90%\xdbb\xfd\xe0>\xa1\x03\xd3\x0cx\xfd\xc6\xa4\x9b\":\x83K\xca\x03\xb0\xbe\xd8\x12\xdf}\xe2\xca\xc7\xc8;r\xd7[\x07m\xdfd\xb2\xdb\xd8\xc9\x81\x90\xa7\xe1\xf2\xcd\x1aSZ\xd7ULR\x95\xa1@qrq\x89\xab \xb5\xdd\xfa\x9bG\xd2A\x98\xef\xf8Y\x0b)B,\x01\x9e\xff\xf5 \xb0\xd3\xd0&\xa3\xe7S.\xbb\xbbf|\x80\xbc\xbbG\x1e\x97e.\xaa<\xda\xd5G\xc8h'\xfc\xc0\x9d\x95\x7f\x9b+\x91dVZ\x08\xc9|\x83)\xcf\xc3!\xf6\x93\xff\xbe\x92\xa0\x18\xb4\xec\x10X\xbf\x97N6'<\x8d4\xd5\x7fLZ\xe7I3N\x18\x14bH\x9c\x07](q\x0e<\xe12pg\x85\x17_\xef\xa74\xdf\x8bY\xbe\xbe\xaae\xb3>1\x99J\x9e\x1b\xe6\x05\xba\xfbWzp;\x02XhY\xd4\xd6\x7f\x87[\x0b\xa7=\x83\xacG*=\x90\xc6\x9cZC\x15sH\xf7+\\\xbe\x05_\xde1\x01\x10\x99\x95-\xcbr\xed\x95\xb9`\x7f\xae\xc1\xe3\x0c\xb3|\xb6\x88\xa3P\x96\xa5\xc5\xf5\x89KPs\xac,\x86K\xfb\xa1\x987\xce\xe0\xa0M^\xe4\xae\x9eG65=<\xc9.\x1e,\xe3\xaal9q\x1f\xae\xa6\x1d\xdc{\x90\xb6\xb1\x03\xe7\xa4\x9c\xb7\xa7y\xf1\xe7\xc2\xc1s\x91P Q\x901\xe8\xda\xbe\xb0\xe1g\x9b\xdf\x1bC\xed=\xbaL9\xc7\xf5b\xa6u\x14\xceli\xda\xf4mx\xe78U\x8fF\xe3\xafa\xe9\x00\x1a\xf5q\x15z\x94\x1d|M\x0b\xdfx\x04\xa5\xb0\x80\x0c\xd3+\x97\xaa\xdc\xf5\x9co\xd1\xe7o\xa3\xeaC\xefZG\x93\xa1P\xbc|\xf4%\x8b\x80\xb0t|\xd2\x80X\xae\x8e\xf8]\xc5\xc1\x86{\x06\xe8\x98\xa5\x1d\xf5D\xfb>\r\x0c\x0e\x17\rME\x05\xa1\x87Xg\xdfP\\\xae[\x18\xf5&~$\xee\xb6\x19\x9f\x98|n\xce\xba\xcc\xcd\x06\x88\xfd\xd8O\x9a\xf5\xb3d\"\x13\xa5\"9\x0f\xab{\xc8xw\x11;\x90d=w\xe3\xb1\xd2\xa1\xeb\\'QX\x1b?\xa0=\xb4\xe6$\x17N\x8b\xc1\xd9A\xa8\x92\x97\xe6\x92@\xf3\x07\xfc\xbeT\x97\xecku\xcdV\x90\xf31\xdc\xaf\xc7\xf7\x8e\x81}`\xeew\x93\x7f~M\x80\x91\xf2@\x07\xe3u\x97\xdavF{\x7f\x15\x89\xa6\x00\xca\xd4\xb0\x0e,5\xb9\xd3\xbb\x8bZ\xc8\xba\xc1\xddP+bF\xbe/K8\xc7\xad_\x84\xd5a?\xdadR\xe6.\xdb\x15#\x8b\x9d\xaa\xce\x15\xa7q/\x04\xab\x00\x9dj\x16\xdc\x81f\xae\xf7s\x06\x84,P\xcf\x98Z\x94i\xdb\r\xfb\xc8\xc2T\xe7\x19\xbd\x1a\xc3\xdb\xb1\xd6`KJ\xc4g\xd3\xf4\xa9\x1a\\NW\xc6\xcb*!;\x9e)\x8ej\x1c\xb8u\xb9d\x80\x8bjg\x9a\xec\x18\xa2\xc5>]+,f\xc3\x16\xee\xc8dr\xec*\xcdE\xfe\xd9e;:\xc6\xefN\xc5`\x83\xb7\xb1Y\xea\xa3v\xd5Ng<\xd1\xa6g\xee\xe5V\xe9\x9f\x80\x16\xc8\\\xf7\x04\xe3\xf0\xda\x07\xabe`\x1a\x94\x8c]\x89r8\xf4\xcb\x9a\x0b\x0e(\x9a\xd8e`7s\xaa;8Bbkz\xc2\xe2\xe7\x9d\x95\xdd;A\xda\xd1\n\xd4\xe7\x9a\x01\xcb\xfb^o\x8e\xfb>\x95%s0\xb2\xcc[`\x80\x88B\xf5\xcfT\x83K\x1c\xcf2\xaa\xac\x97\x8f?\xc8g\x0b\x16\xa1BP\xdeZ\x8e\xce\x0e\x07x\x04\xd2\x0c;\x98J\xe6\xb5+\xc8\xa0dT\x9b@\xa3\xa5\xc8\x0c\xe6:\x12\xcfg0X\xb4\xb6\xf1\xf8T\xd8\xf8\x0b9^\xd3\xb2\xe5\xd0\x8d\x93oV\xef\r\x19\x86])\xd0\xd1J\x94\x82L\xa3\xdd\t\xaca\x9b\xc9\x18\x02:?\xf1\xbf\xe78\xba?\xa6\xe3\xd0\xb3\xdeL8*\xd7\x9fSd\x18\x8b\xb9\xa8M\xa1\xdf\x17@\t\x9a@=wZ\xd9~\x9a\xa3O9\xf0\x0b\x93!\xa9+\x9a\x96\xea\x89\xc5!7\xe1\x95L~\xe01\xcdQ\x92X\xfdJM\xf9S\x13\xad\xab\xce\x9f\x1ck\xfcP{M\xa0a\xa7\xd8\x8c{\xaa\xdb\x11>\xdc\x8az(]l\xa3U\xdb\x15+\x9a+\\8\xc7\xbd0\xc1\x98\xc9O\xb0\xfb\x07i6\x98I\x1d\x1a\xe8b\x9bc)\x94x}\xd1y\x86\x94\xe6X\xd4\x1c\xa1\t\x9f\xdb\xe4Z\x16\x8e\xa2Z\xf9\x8boj\xf0\xbd\xa8e\x92\x13\xea\xb8\xf4\x99\xa9]\xf4!\xf6\xbb\x9c\xc8\x1b/\xf5zR7\xb6u\x7f\xf8\x929\xbb\xf5\x12\x02\xc6\x1e\xdbm(>\x94\xe5\x17\xd3\x9c\x03_0\x05\x16\x93S\x90_\xc2\xd5\x00s\xc8\xe1\\\x9dk\x93\xc1\x1e2,\xbc\xe4,q\xf1\xa2\x16\xf1\xac\x95\\g\xe59\x1a\x1d58\x1c\xce\x9d\xa8kp\xff\xc7\x0c\xf6j\x82h\x13V\xdd)\xee\xd9(\x01\xc7eN\xa3W\xb6\xc9\x83x\x92sM\xde}\xa0V7\xdf\xc9\xeb\x0c\xe30\xf0\xe1\xbdOUQ\xba\x1f\xd3\x03\xffr\xd3U;w\x06n\xaf\x89\xd4\x8f?\xe0\xea\xa8\xea\x03\x18\x89\x9f\xdf\xdc\x023!j\x84\xf3\x87\x8e\x01b\x9b^\xf5\xda\x94\xfe\xbba\x7f\xe0?\x17\xc1\xffb\xab\x05\x81\x99\xffH\x19\x07\x91\xfe\xc4\x7f\xf4r\xa63j\x83\xce;\xa9\x08\xb4\xd6\xd7\x99\xf7\xe3sm\xb5\xc9hmAD\t\xbd\x89@\xfd\xeb\x9b\xf4\x85\xcb\xa8\xedG\xbf\xc3o\xaa\xeb\x9cK\xf8\xf9\x08*\xad\xa2\xe7\r\xd0i\x8df\xe6\xf6\xc3n\xbf\xd0\xe9\xe0M\xb4\xf1[lf\x16gS\xa0\x9f*\xcdWI\xa8~\xd6\x10]\x8c_\xb8|\x19 \xc4\x00\x93~\xa7k\x9c&\xbf\x9a\xefhU\xdd}\x14V\xe9\x11\xed\xe2\xf3\xeb\n\x0c\x87e\xb49\xf3eh~\xbc\xe5d\x1b:\x0c\x06\xf9\xffJ`\x96\xd1\x82h\xfb\x94\xe5\x07E%\xae\xed;i\x9e\xaf3\xe4R\x8c\xef\x0f\xae?\xf9Va\xc74\x12\x8f\xea\xd5\xde\x8e\x90\xcd\xbe\x15\xf6\xf1\xa2\xf7\xda8.\xeeR\xc8\xa7\x8a\x1e\x90\xa8-\x97\xf9\x1dl\xcf\x9e\x08\xa8SQ\xab\xf2\x8e\xb8Y\xd5A\x930s\xa2\xe85\x89-\xf5\xf1\xf1\\\xcb\xa9\xe7\x8e\xffn\x9aXut_:`\xeb\xf4\xc1B%{H\xc9\xa2\r\x0f\x1f\xbc\xcad\xfbdI\x1f\x8a\xa7LZ\x98^\xda\xda\xd2\x9e\xe4L\xaeS\xa4PD\x91YT\xcem\x1d\t\"9jepP\x04\x13\xca%\x06\xb9\x96\xf3|\xa5%\x04d\x83\xb5\x87\xe2b\xa5@\x1f\xba\x07\x97\xe8>S\x8a\x82:\x8f\xbb\x0f\xb2\x86\x8a\no\x8bd\xbf{\xe4\xa2\x8e5\xc1\xd5\x8b\x9e\xd0\x87\n\xe4\xd2\xafv\xb9\xe7\xba\xfc\x17\x01\xbd\xcc\xa4Q&Fl\x1cy\x87\xb2\xc7B\x8d\xb0\n\xab\xcdC\xd6\x9d\xe9Wp*\xa8j\xbe\x82\x91\x13\xda\xb1^\xf6\xca\xb7\x14\x85\xb1\x07(AH'g2\x00\x89\xbd\xcb\xf30h\xf8\x1b\xf4\x867\xcd\xfe\x1a\x1d/!\\\x85Y\xd2\xa1\x03\x05\x17\xe6\xd1m\x99l\xb1:\xb1\xadu\x8a\xef\x91H\x81\x81\x12\x8bc\x1e\xc5\x06\x0e\xadMbY:\xf2\xc0\xb3\x1e\xe3\x1d\xd0O\xda\xb81\xccP\x11\x82\x12\xd5\x91$\x7fU\xd2m\xa8\xa0\xbd\xb3\x8f\x9dMfL\xd474\x19\x81c\x81\xb1\xab]WTt?\xc3\xfe\x7f3\x15\xbep\x02:\xaeV\x8e1\x00\x06\x12G\x1d\xa9K\xbc\x93Dm\x8b\xc5\xb9\ta()H\x11\xd0z\xf6\x10\xf8\x9c\x01]W-DM!\x121\t\x01\xdc\xf1n8\xab\x82+\x1b%\x0cG\xf9\xadAt\xfb\xc1\x05\x81`:\xfe\xc0\x17\x92f\x14\x119\x80\xff\xc3\xb2=\x8d\xa5i\x86`\xf1\x06\x81\x1b\x9b\xcau2\xf1\xe5\x82\xe4\xe3\r#u\xae4\xb0E&\xd8\xacy}\xa3\xe7\x0c\x8c\xce\xaaJ\x8d\xe4\xcf+\x04\"U\xb5\xb7\xafF\xaf\x97\x04\x94}\xfb\x88\xdb\xca\xc0\xe2\xd8\x08KU J\x0fe\x16N\x92\x06\xbbr$n\xa1\x0e\x08ed\x946\n0_\xb3;\xb3\x9d\x0c\xce\xc7\x85]\xa5\xf7b\x17\x82\x7f'\x8c{dg\xb9T]N\xc6;[\x9a~[\xcd\xc4\x02\x98+:*\xae\xa7%\xc5{\xc7\x05\xb8\xfa\xc6\xc5|\xe9\x92G\xa4\xb1\xa6G5\r\x94.\xbf=\xc9\xc3\xc8R\x0fa\xb5X*\n\xc1\x11q\xf37\xec\\\xf9_n\x7f\x08\x1e\xffV\x95y1Nx\xb9\xbaIJ\xf9\x14W1\xb4\xdb\t\x01r\x1d\xc4\x1a\xa0m\n\xb6p>/\xae\x05Z%P\x88$v\xa9+\xdd\xa8r\xf7B.\xd4\xd4\x97(\x1a\x14X\x94\r\x0f%WU(\xb4\x10\xdb\x14B.L.\x1a\xca\x184|\x9c*\xca\xa8\x82\xe3\x12:\x1c;\xa5\x83\xe4e\xebp\x12[\xcc\xf1\xb3\xd3a\xd3\xf9\xd8\x1f\x94\xd54\xdeX\xe2a\x9b\xa4tn8\r5\xaaX\x99\x0e?\xf8#l|!\xaai\x0f\x17Y\x98\x85\xc9b\xa8\x1cK\x11H\x05\xaf\x8c\x05\xab\x87pgwX\xe8\x7f\xc9\xd0jU\xd3\x1drs\xfd\x07\x95S|\xd3\xe1\xba\xf7?\x8d\"\xf6px`\x8e\x04\xea \xee\xb8\x15\x9b\x15\xa0\xb9W\x1f!\xbf@\xd6\x85|\xba\xab\xe9w\xa4\xa4\x11&\x8a\x14\xfcl\xe9\x94\x1e<\xdd\x92\xa7>\xf6+\x1a\xf4\xee\xd0\x08x\x1f\xe8s\x18j\xc7BAsi\x9bN\xc5\x87\xd5!\x8f\xe7\xd1\xedQ\x162#H \xcb?\x8a\x8d\xa2(\xbf)`\x7f\xac\xaa0S\xfb\xcf\x15j\xd7FU\xf6\xd4lT\x1b\xf3.x%\xdb\xb1\x12ttBQ\x89\xccF\xd7\xa5\x12\x05\x13\xbcM\x8d\xc3\x7fr\xe2\xfam6\x88\x8d\xaeK\xc2\xb1\xa8\x82\xd1lb$\xa7\xffB\xf8\xa3\xe8\x89:Bpe\xe6\xde\xcf\x91\xe1X\x18\x00%\xb4\xeeTs\x05\x1b\xeb\xe9\xe4\xa1A`\x1e\xf1\x00\xfe\xd7lj\xe3$R\x1b'K\xe48\x14)\x04\x02a\x8c\xe4\xae\xc8\xa5\xfb\x82\xf3\xb3\xd40\xd5vH\xf2\x94\x8c\xd1\xc0\xfa\x8f\xaeO\xbd\xfb\xf3\xdc\xd4\xc25\x81\xb6r\xffD\x113e\x9be\xab\xb0\x1f\xef\xf6\x8a\xbake\xc2\x1f\x93\xfa\xa5\xe9b\xb0I\xeb\xa3f\xa0\x8d\x02N\x88\xe3\xe7f\x01\x0bYQ\xf1LR\x9f\xf9F\x9a\xcall\xf2UN|c\xfek\xb7\x08\x8d\xd5K\x00M)(\xd4C\x11\xd6\xb3\xd1\x19\n\x08xyAb\x17'\n\x08\x19\xaa\xe4F\xbd&\xaep_\xdeV\xdc\x1c\xd4\x02\xb9M\xe9\x08\xbd\xec\xbf\xb4\x8f{\x12\x98\xa6\x10&\xa3{\x92\xd9j\x91zo\xf9/\xcd\x84p\x1e\xc5\xb7\tI\x84\x0f\t\xdc\xb5g+\x94\x84\x82\xc6D\x1f\x13)\xb3\xa0\x8e\x8d\xba\xd2\xc7\xe3\xe9e\x8bS/\xd8*6\xd5w&\x86:\xa6\xe8\xdd\xd4\x929\xe3/\x8b\x8flrj\xa7S>]A\x8a\x12\x9apC\x1c\xca\xf8\n\x1d\x93\xd8\xb7\x89\x7fF\xea\xcf\xbco\xf5T\xbb%\xbb\x12\x04K \x8a.6s\x03\xed\t\xda\xa3\xa6\xc6\x920\\\xc2\x8bm\xa8\x9e\xa0\xa7.\xca\xb1\xdc13\xa0(\x8dP\x12@3\xfb \xb0M\xaf1\xa3\xb8vMb\xab\x88E~\x1b\x81W\xda\xfb\xed\x97?k\x17X>\xca;o\xb3]H\xe7\xf6>\x84\xd5n\xaa\xc8)\xb7\x89\x0f<\x9c\x0c\x0fZ\n\x14\xfel\xcfk\xa0\xba\xec\xf0]\xc2%\xa2\x9f\xb9\x93\xdc\x8e\x7f`-\x08\x7f2k\xad\xc9\x1b\xbd\xc3\xd3\xfa\x06\xc1q\"\x13jR\x9e\xa2N>\x18\xfd\xa4]bb\xc7b\xd4|\xe4\x1b\xa4,\x9a\xdb\x80\xf3\xf7!\x1d5\x8f\x9d^D\xca\x97\x8cCn\x80\x86O\x94\xf5\x8b3\xb5\n$\xe7\xa2\xaaI\x84\xf0\xca\xf3#Q\xd1\xfe:\xb6\xa9\x15\x98\x05\xea\xb6g\x81(\x00d\x15\xef\x87\x80\xd2iU\x96\xe3Q\x9a\xd7\xa0\xc6\xdbJ\xa8\x13\xf7[,:\xe2mQ\x1c{5x\xeb\xd6\x99\x92\xba\xea\xad\xd7\xa8\xa1N\xd6\xb3u\x08G \x8co \xc1\xe2\x93\xe5\xfc0/\xcd\x9d\xb8p\xab\x88\xb1\x80#\x12\x00$\xbf\xc7h=\xf6\xdb\xb2\xff\x02W\x93v\xbf\x867\x06V+\xc4\xe4\xef\x93\t\xac\x0b\xc8&\x87\xd8\xf1\xa4\xf4b\xac\xd4\xa9\x97\xd04\x89 \xbcWK\x03\xc4\x8dOu\x80\xd1\xeb\x18j\xfaXK\xb6\x02\xb4\xd4M\xf7\xce)\xb1\x94\x90;\xd4\xeb\x9cX\xabG\x9fF\xf0\x10\"$\xe9\r\x91\xa64\xf8\x15f\x0b\x86K\n-1\xe2B\xc4\xaay\xeb\x05\xbfm\x0c\x8d\xac+T\xb4~k]v\xe0\xc9\xc8\xa0\\?\xd6\xc3o%g\xa9T\x97\x03\xb1\xa5\x88\xab:\x9c0\xc6\xb8u\x14\xb4=v\x91\xec\x01\xa63\x83\xb8\xea\x9b\xef\x0fQ\x03!p`\x9a\x14\xae\x19\xf2\x85N\xd6\xb4\xb6?f4\xc6\xa2\x89\xa1\xef\xae\x8a>\xba\xfa\xb8\xf4\x9f\xd5\xd3\x14\xeb\xb4:\x0c\xbc\xe9Si\xa8\xff\x19\xb3\x0e U\xbb\x0b\xc8\x8c3\x83Oa\xd4@\x15\xcf\xb5\xda\xbdXMt\x1f\x15\xf9\xbc\x1b\xe9\xd9\x9b\xa21\x11\x9bI\xc4B\xdcME\xe2\xc2\x04\xeaI\xf0?|\xf0\x99V\xde\xafL\xe04~-vg\x15\xbc\xed\xc4\xf63;\xa8\xfa\x1a\x1d\x16\xdc\xf2\xb6I\")\xa0$\xbc\x86B\xbf<\x97\x88\x83\xae\x13\xa7\xb8\xe9\xfb\xc0\xfb\xe3\xbb\x95?\x1fH\xfd\x9ab\x99\xb6|>\x08\xb9_DN(\xb8n\x9c{<\" I]\xd0F7;N\x19)(\xe3P\x80\x7f\xae\x12\xe5Y\xb20S\x90n\x1e\x01\x88}\xcb\xfbXC\x9d\x94F\x1a\x1a5\xda\x85\xc43\"iH\x06\xb6\x82\x00\xdb\xa5\x96\x90\xa4|\xfez\xc4\x9a:h\x04g\x0f\xc9+\xc6\xcac-\x90\x00'\x17\x8e\x0c\xc8\xb8?\x90e\x02\xc3!\x15\r\x03\xc0\xb2\xf5\x17(`\xac!\xdf\xfe`\x92(\xeb\xf3\xf9\x8e\x9c7\x00nGo\x18~\"\xfb\x85\xcb\xfa\x0f<\x93E~\xcd\x80\xa8\xd2\x96\x83!\xb3\x80\xcd\x81\xde\xdc\x9b8\x03\x04\x80^\xbbV\xcce\xe2!#PD\xaf6\xc4\x1f\x92l\x89\xae\xc6\xa6\x12\xf0PY\x9d\x11\xb5\xa0\xca\x14\x8e \xd1\\\xcb\x14\x84\xa9\xdd\xba\x16;\xdc\xe8\x8c\x02\x1e3\xbb\xaef4|!\xc4\xb5K\xa6f[e\x12\xc5\xe73\xca\x00#\x81\x07\xcf\xc6\x98u\x91\x12\x14w\x04\xc8\xe5\x82Z\x1du\x06\x04\xd6\xc2\\\xca\t\xb5\x0cx\xd2\xb5\x92\xac%\x9c%\xe4\x03\x0b)\xb0I_g\x9e\x91\xa6\x04\x01~2q\xf1/W\x90P\xb5\x88\xcf .\x97Y\xda\xd4\x920\xe6\x9b\xb0j \x1b\x16\x0b\xc7\xec\xa5J\x003\xf7D\xf5%\xf2}\x84\xb5\x12\xbe\xb4W\xe8\xfeii\xef\xbe\x1c\x07\xb7T]\xeb\xe2\x18s\xc8\x8f\xc7\xee\xe7r\xd6\x84\xc8\xfap\xfb\xa7\xb2\xf4\xa3G\x9c\xa0G\x98\x9d\xba\"Z\xbb\xcb\xdb}\xd3\x99\x07\xf9\x02\xa3'\xb8 \x93\xafs\x88)\xb2\x0eB\x075\xc9\xa6u2\xd4\x13\xae\x19\x12\x14\xefE\x9f\xb2&\xd6\xfe\xa8\xabY\x0b\x1ac\x18q\xfc\xb8/\x95\xc2#f\x8e\x8b\x7f^e\\ \x0b\x96\x08\xb5\xa6\xd7\xd9[\xfe\x88\x8c\xffM}Z\x13\xd8\xff\x8a\x16J\xa3\x89@-\xdf\x9721\xf7\xfa\xb2\xd2;\x00I\xc9\xb0>\xf8\xd8\xee2\xa3\xeb\xbb\x0b\xe3J\xc8.e\x8e_K~9\xa3\x9b\xe0\r\x8b$\\\x13\xb8\x8f\x1a\x19O\xbb!a\xc3\xff\xec\x85e1\xfc\x98\xff\xcc[\xd9\x07j\x1d\xea\xb3\xb5Z*\xa6g=\xfd\x9d\x1bc\xd20\x88\xde\xa0\xfe\xaf\xca\x08\xa34\xb2\r\\\x01\xfd\x97\xf0\xc3\x81\xd4\xbf\xb66\x0el\x1f\xd5c\x1b\x9d\x96\x06\"k\x9c\xce\x91Iu3\xb9q\x19\xb0\xf5\x08\xcdc.\x04\xfd\x7f\x85\x1d,\xe5Jb\xab#^\xfc\x008\xb9\xe5\xf5\xb94P\x9bk\xa9\xd1E\xbb`\x02O\x9e-8`\xd0\xe3\xe80<#\xcd\x8a\x03\xdc\xfcT\xf3\xc0\xd19r\x81\xfc\x94\x9f\x7f\x95\xab\xad\xaf\xccpN\xa9\xc9v\x7f\xf9\x7fF\x8c\xbc\x00\xf5\x99\xd1u\xb5^s\xa9\x8f\x98(\xca\x187\x9a\xd2c\x82~\x04\xea\x97/\x19\xa1N\xf2c]U2a\xd7\xbe\x83\xa0\x82\xa2w\x11&RV\xa4/\x94$]\xeb.\xd9j{$\x96\xe8\xd9\x82\x81\"\xd8\xf3\xc9\xce\x89\xdc\x00=5\xa5}\x15t\xafc\xb0\xba;\x1c\xdb\x94\xc1\x0e\x8a9|\x05U&\x1d\xa0\xf3\x19\x89\x13\x8f\x87!\x88\xac\xd4\xe5\x99\x00Q\x80\x11'A\x12\xa3A]gJE\x9f\xc0t\xc1c\xcf\x98\xa6\x8a\xc3\xd8\x8aF\xbd\x00\xe1\x01\xaf\xca\x98*b\xb0F\xfd\xefP/&V\x00\xec\xb7\x0c\x95\xc4\xe6\x80:\xb7W\xa8\x9b\xce:\x01\xb2\x90\xaa\x9f\"\x14\x05ul\x90\xc9~b\xa0\x1c\x9f4:Q ~\xdfh\xcec\xb2(\x87\xbb\x1b\x9a\x92\r\x97X\xed\\\x0b\xe1\xec4\xbb\x9c\xe7\x89\x1dz\x94x\xfe\xa6Rx\x12\xc3\x86z\r\xf3)\xce\xf0G\x02\x1aG\xca\x87\tl\xc0\xac\xd0\x92\x1c\xf9\x87Kny\x8c&|\xf6T\xe4\xd1Sn\xd3\xf34w\xee%u|\x86\x85\xceQ\xe1\xd3\x80\xaak\xf2W\xde\xda\x1b+\x18\xb4\xd9\x86R'$\x0f\xa8\xd2\x17\xc9b\x15[\x8d\xf1kd\xc7\x08s\xda\xf3<\xc1\x1f\xe7\xd1.l\x0fmd\x00\xe9f\x94p\xda\xbeE\xb8>\xbdKa\xc7'(\xedIs\xc7\x8c\xe0\x92\xec\r\xfb)\x0c\xdbJ\x80\xf8\xca\x07RP\xe3\x94\x1c\x86;\xa6\x1d\xa4\x1cs\xc3\xd7\x92\xe4\xbb!\xde+\xce\x1e\x04\rw\xac+\x832\xaa\xbbop\xb3f~\xc1\x9b\x86\x91v6\xc9\xfd\x16\xf3tX\x99d\x04Q\xc1\xf4\xe4]n\xb9B\x14\xcc\xb9\x02Q\xd9=\xe9M\xaco30O\xacq\xb9;s\xfb\x01\x1cT\xe7;\xc2\xd2\x0b\xa3\xd97Y\xb9\xa0\xcf{\xafdw\xab_\xb7\x992\x81\xb3\xb4l\xfa)\xf9_\xf9;\x7fO\x94C\xe8\xaa\xfb\xa2MT\x8f\xdf8\x96uV4\xc1\xf35G\xcbj$U\xd6\x1f#@\x87M\xe1\x15B\t\xa7S\x1a\xa5\r\x98\xc2\xf8\xbf\xa8%@\xbevYj\x85\xa8\xf5\xe3n\xd0/L\xda\xed\x19;k\xbb\xb5{d^\xc2I\xff\t\x0e\xf6d\xcf\xc3\xcb\xa9[\x9b\x04\xe9\xba\x0flj-\x86\xd8\xc41\x9bA\xd0P\x83\n\x103\niI\x86S\xaeK\xf5\x8f\xf5\x89\xde\xc9#\x97\x98U\xb3\xa2d\xde6\x0f\xcd\x08\xd3\xb0SA)\xdf\\)]\x9f\x90\xd6\x84*\xbc\xe8AY\xb7]\x05\xe6\xc6\x8b\x96\xd8\xa1\xe8m'\xe74z\x0e\x87\xb3\x814e\xc8Aw\x07\xec\x8ah\xe5\x9b{\x0f\x8a\x8cG\xaao2\xd4A\xdfA\"VZ@\xc3^\xe3\x8b\xc8\x03\xca\x99S1g(\x08\xe9\xe7C\x8aR\x9b\xc4\x9d=YQ\x87\xd5N\xd5\xbf\x1a\x13\x84r\x03\xc7\xc9$Q\x805\xedWv+dZA\xa5m\xd3\x11*\r\x1f\x00$;\x99g\x06H\x00\x9f\x93\xfa\x16\xda\xaa\x99r\x91\xc2\x14\xfbmm\xfafn\x0c\x82|\xb6t\xb8\x83\xd7^A\xc4\xe4\xf0\xbc\x98\x17\xa9\x17\xe7,\xd7\xc9L\xfa\xa0xH\x95d\xa6\x82\xe8\xff]\x11\x11\x9c\xa8:\xe6~\x1f\xc0<\xc3\xbc\xc3\xe3\xff\xd0\xa0\x8b\x98\xde\xa8\x9d\xf2y=n\xa6xj\xc3}\x04f\xc7\x06!\xb2\\\x19M\xcd\xb2\xbaH\x84!\xb9\xc7\xea\x1a\x8fi\x7fh\x06\xf5{\x9dYg\xa0b\\<\x9c\xe0\xc4\xae`\xec\x17^\x01q:zn\x9aJ h\xae\xb8\xbe\xad#O<\xc7\x83)\xe1\x86,\xd9}\nM\x05\xd2\x86%\x1b\xfb\xfb/\xd7\xd9?\x1fD\x8c\xc0\xfa\x7f\t\x1c\x81\xc9\xa3\x93~\x1e\x8f\xe2\xddc9\x04\xb0\xb8\xe5\xee\x1f\x88\xedaq\x86D\x9b7\xc4\xdc\x99x\x9c+?8N$w\xc8\xa7\x17\x0e\x00\xef3\xe1\x8f\xfb\xedp\xca\x82!\x92H\x08PE\x17Ot\x13\x0c\x01\"(\xd2\x1b\xbff=\xd6\xf0P\xed\xed\x83\xec.\xda\xb4d\x02\xb3v\xf6k\xef\xa3\xfc\x14\x82\x16\r\xb5\xe8quE\x0bE\x16\xedq\xca\x97\xbf\xbd^\x92\xe1j\xbc\xf5\xf0\xfc\t\xf8\xa6\x9a;a\x18\x10\x04\x07R\xa3G:qQ?Ee\xf5+\xd6\x7f\xec\xe9\x1e1\xb5[\xe3h\xd1\xdcY~\x8cj\x12\xb3\xb9\"\rj\xeaX|\xbe\x9ej\xb9'\xc5\x9c\xfcE\x9e\xfd\xe7E\x95\xab\xff\x87\xc5\xb6\xe4J\xfe\xe3s\x04\xc5B\xce,\x01H\xeb\x04\x03\xc3\xe1\x1a\xa4*\xcdnq\x99\x87\xbb\xf5\x92\xdbf\x94~z\xdc\x14]h\xd2\x91\xb1\x8b`w\xb4o\xd4\xc2tv\xfc\x0b\xde\xe1\x81D\xcf\xc9J\x91G\xb7\x07X\x0e\x12\x1c\xde>K\xb9!\xc1\xeb\x9a\x8fF\xec~\xdc\rF\x9e\x10\xe7;J3\xcc\xdb\x97\xfe\x03\x8e\xdf\xb7\xa4Ax2G\xd7\x8d\x08\"\xf6\xea\x03\x8c.(=^9\xdf\x12\x95\x10ME\x97\x0e\xda\xe7I\xdbcw,\x81\x16\n\xcdW\xe9\xee0\x01M\xb3\xe0\x8d\xc2O\xc2\xd7\xee1f\xbf'y\x1b\xf3*\xb68\x01s\x1a6:\x0b\x80-\x12\xbc\xc8_\xc6\xfc\xbfe\r\x08n\x81\xd2w0\x0b/\x94\xef\xb6\x02\xf9\xc1\x04\x19\x05\\h\xb7x0U\xff\xc7\x9e]k\x9a\x9f\xe4\x17\x18)S\x13\x89\x80\xfc\xb4\xb6V\xd2\x1f\xe8D\xcb\xd4\xec\x08\xcb5PA\x05\xf8rwb\xdd3\xe7\x19N\x9f\x8fw\xe4\xfdK\x97\xc6e\xb5D~\t\xc4\xfa\x07\x0e\xfd\xa9S\xbd\x91\xf1r\xedB\x86\xf1\x96\xb4\xff9\xa8|\x14H*\xf6W\xd8\x9dO\xb3\xdf\xf8\x8f\xab\x0c`Z\x9a\xcf\x81 \x06\xff\x9f\x8c\x9c\x11wCb\x8a\xbe\x89\xcd[wv}q\xc5Ah\x8e\xb4>\x01\xb6\x0b\x0e\x84\xa8\xc4\xdf\x9a\xa8\xfd\x99\xba\x80p\x9a\xc2\x8f\xabk\xebq\xc1\x96\xbc\x972\xb8\xf7\xed\x80\xd5xfF\xec#\xe528\x14\x97\x08\x95e\xb2~=\xb1\xe6j\x83<\xe9\x9b\xf0\x12\xcd\xe8B\x8e\x96z\xca\xafQ\"4\x99\xdc\xa8^\xfe;\x89e\xdd\xd6\xb4G\x17\xea\x1a\xa3\xbf%bb\xca\xa3\x05.r: \x10Z\xdf\xd4g\xb3g\xe6\xb2\x96Nw\xed_Z\x16\xa5]X\xa3w\x14f\xe1\n\x9d:\x0c\xf82\r\xbep\xa8py\x97U\xc6\n\xe8D\x89Q?\xc5\xe2\xca}\xfc'\xc9\xf5\xf1\xbc\x9b\x94\xb3^P\xbd\xc5.'\xc6\xc5\x11\r\x86(\xee\x95>|\xfbY8r\x89o{\xe4\t\xb9C$`\xaf8\x7f\x16E\x16\xac,\xa2\xabue\x86h\xcapa\x0b`\xad\xb6\xcf\xd83\xa4\xb6\x11\x9c\x8f\xd7&\xd9\\Y\xfdo\x1a\xed\xf3\x02\xca\x9c`E\xe3\xc8\x16c\xd0\x13\xbc\xe6\x9c8\xed@\x89)\xefA\xfa\xee\xc3\x9ej\xe9\xb2\x05\xc0\xaah1_\x0c\x03\x1f~\xb9/T\xb6\xc0hM\xe4S`\xc48[y\xee%2\xa9\xd0\xf8\x1fs|\xba\\\xd5\xad\xf4/\r\xb2\xd2\xdc\xf0_?\x83\xd9\xc6\xa3w\xb7\xfa5\xf1'\x1a\x8e\x1c\x92\xd9\x12\xf7H\r\x11\xb0{\x01\xc9g\xee\"]\x1c\xadBr,\x8cS}\xcb\xf6o 8\x82Ca\x80\xa8:}\xce\xa6\xf4\xd3\xea\xa4\xdf.\x16Y\xd3\xe8\xb5\xee\xe5{}N\xb3\xb4d\x8amq\x8a\xa4\x9f\x15\xc8/l\xe2\t\x96\xc5\xe8*\xba\xbe\x1f\x1f\xd1\xab+7\x01(\x9e\x9b%\x05wX\xff\xe1y\xd2\x8e\xf0\x9aB\x02\xfcz\x00~\t\x11|\xb6\x8e\x94\xb9=\xdc\xf8\x83\xa5C\x14\xcd\xac\xad\x83\xe5\x9b*\x0f\n\x8b\xc4\xfc\x14\xefW-\x0e\xecVs\xae\xe0\x86\x83\xd1B\xbe\x02XN;xC3V\x1a\x10\xea\xbaVM\t*\x00\x92\xa7\xb5~BB\xf2\xb4\xd3U\x93p\xbfd\x16%\x9c05\x84fN\xdb\xf9\x1b5e\xa0&\xad\xbcsNuY:l\xd3ib\xb7D\x83@\x1c\x9dK\x9b\xf0q\xf2o\xb4[\x97o\xddUy\x9f\x93\x03\xff\xb9\xec\xd8Q\x8e\x11Q]\xdb\xe3zz\x89\xcb\xca]Z\xd3\x01\x02\t\xc1o\xfc\xa9\xbd\x1a\xf9\x8a\x85(9\xbf\x8e\xdd\xb8\x9cm\xb6\xda\x95\xe4\xcb\xbdel\x7ft^G\xa8|\xfe\x9f\x90`\x9c\xad\x87W\xdc7\xdb\x887\x11w{\xb2\xae\xbbtt\x06\x81\xb4\xec2\xbcz\x8a D\x16\x0eO0Q\xc0\xd9\x84\x8a.\xe5Q\x9d\x8e&\x9fa\\A\xfb@\x86\xf7:\x82\xbd\xf4\x13Z\xeb\x86:QJ]?D\xa9\xa8g\xb4\xc1\t\x87;14\xb6\xe2'i?I\x1eHs\x94Z\xe1\x19\x7f\xb2\xf5\x90\x9eK\xe9\x1e\xed\xd7\xe3\xe6\x0c$R\x88\xfaB\xc8\x92\xde\x05@\xda\x96\x92G\x87lE(\xaf'\x9e\xae\xfaR\x1e\x0bC\x9eH\xf7\xdf\xe3\x9f\xe0\xf9T_t\x8bB\xcahh\x81\t\x98\x82\xa1j\x17R\x1f\xf1fTl\xec\x91A\xf1t\x1aR\xb7\x7f\xb3\xbcBZ5\xb8\x1co\x9eN\x1d.g\xee\xf7$\x85\x87f\x90).\x10\xb6\xf7q\xf9\x94zP\xb7\xdb\x9b\xd39\x1d\xc0\xd6\xfe\xff\x07x\x1c\xfb\xaf%\xbd\xbc\xc6\xba\"\xf6|\x10\xd75\xc3+\x18\x1a\xfb\xb4\x11\xed\\\x8fh\xd9\xc0\t\xa1\x17\xccZ|Z\xb1\xb8\x8e\xc9#\xf9\xd6\x8b\xbf\xdfn\\\x96\r\xa0=0\xbc\xe8\x84\x0b\xef\xeeR\xfe\x1f\xf7@\x02\xbbR\xe9\xbb\xcb>\x8fS^\x0f\x92\x7f*\xf7+\xcd\xca\xdc\xc8p\x06)\xc1 \xcdz\xab\xcb8B~\xaf{}\x19\xc6\xeb\x8b\xdd{j\xe0\x01\xe4l.\x19\xd3T*\x8d\xc7H\x07k\x8b\xfd\x8eg\xcd\x89\xaa\x8a\xe6\xfb/E-X\x8a\x89\x02\xa2\xcd\x13\xacN>\xbc4a\x18W\x02\x95\x9e\xa4z\xff\x05\xf5\xa9\xb0,`*\x11}\x1cz)1\xf1\xe0\xb8\xc64\xc8\x032\xcc%z\x80\xb1\xec\x7f<\xc4\xfentJ\xd1\x10\x90\xab\n\x96E\xe2\xa2\x00L\x1dO\xe2\xaet\"B\x0e\xf4\x8d\x8c\xb7\x8fA\xbe<\xcb/z\xd6\xae\x02(\xb8\x9dL\x85?\xe7T\xba\xd7\x961\x8d\r~\xa0\x9e\xe0\x12\xd1-\x8dc\xb8\x06\xc4\xa1\xfe\x1d\x8f\x03\x86\x9a\xeeh\x1c\xdb\xb8\x96\xfcc\xfa\xd4\x13\xfaX\xa4#N\xd2\x0c\xfe4\xbdB\xb1v\xa6>\xbdE\x9c~\x1f\xc3\x17u1C_\xa5\x84d\xe8\x9f0\x9f\x98A!\x16+Go\xe6s\x95EA\x8av\x1c\x1d\x83\xabZh\xef\xe2zS,.\x1d\x91\xfe)\x19l\xfeyAR\xc3\xa1>\xe6\xb1\xef\x9d\xaau\x1f\xf3\x86Y\xf6%L%\x932T\xf3\xbc\xcckX\xf4\xebGa\xffV\x92M\xd0C\xd4Kn\xee`\x98\x84;{P(\x9be\x01;\xd6\x16#88\x0c\xcd\x97\xd7\x14\xdf\x0c\xa0\xedDc\x82W\xe6j\xa6\xbbH\xa5\x9d\xcb\t@\x0b\x10\xfd)\x9ai:\xd4\xe1\xbcU\xfdLs\x9d!\"2iRI\xe5\x93\xa1'\x86\xd8\x90\xbe\x96\xc5\x04ul\x15\x95`\x8b\x17\xeb\xef3U\xf5[\xbcV\xe5\xbf\xfc\tq}\xb9@\xb9+\x80\xb2\x02&\x7f\xc7^#\xa3\x8c2\x862\x19\x12\x97\xbd\x06\x86i\xbck)N\x05\xe7A\x13\x9d\xf0?\xd0\xe0\x10\xe7Y\xd0\x83\xf5\x1e(\xaf\xaf6\x04\xb6\xe5\xb0E\xa0\xa6\xe1\xa7\xcc\xd1\xbe\x89\x9f\xf1 b\xee\xecp\xa8\x08\xdf\xdb}1\x93\x97\x984yG\xe1\xf3\xb8\x14\"4\x1cfL,\x953\x88O\xb4\xfcv\xa2\xae\x9e\x10\xc8\x91\xa7\xc7\xcb\xff<\x90\xc0ojKK\xf2\x16\xfc\xf6rm=p8SJK\x1b+oey\xedp\x8e\x81\xa9\x9c\xaf\x12x\xc3\x8c>L\xd1\x82\xe2\xbb\xc8\x16\xc5\xf4\x0eQ\x9f\xd6\xf8\xf55wu\xc9\xf8\x0e\x0f\xf183\xa2Mc-\xc5\x80Rpu\xcbJb\x84\xb1\x1f\xc2\xb9\xc1\x07\x96\x9f\xe5n[N\xc8\xafW\xfb}2qM\xe2\xc9\x8b\x19\xe0\xc2\xc6\xc5\xc4@\x88\xf7\xca\x88\x9b\x0cC\xd0*\xeb\x16\xeb\xef/\xb3P\x96\x1e\xf3\x8e\xc9\xbf\x975`%\\\x04\x15\x91\x89TV`\xc1O\xea\x89E=7\xfc\x9a.\x98\x8c\xe7\xd0\x86\xf5+\xd7\xc0[g\x0e\xab\xe1\xed\x07\x10Q\xbe\xfc\x93 \xd7;5\x93?\x85\xa41Y-\xd23I\xf9\xf8\xb2\xc7\x7fX\xe7x'\x87fF\xbbp\xeb\xda\x0f\x94t^\x84\x8bz\xeb\x1b\xaf\xba\xb9A\x95\xd8\\\xca\x91\xea\xc3I\x97\xd4\x86\x8d\xffM\x9b\xde\x82AA\x9f\xab\x17_\x9d\xd8f\x87\xc3\x93(U\xd8\x8a\xfc\xf7%\xd1\"\x0c\xcb\xc8\xa2\xbe\xe3\x0b\x11\xd0\t^\tHf\x15\xac\xa7\xd6\x0ekDq\x036O'\xf6\x86\xfdS[{u\xdf\x97\xc7\x96\x9b-\x88\x9f\x86\xece\x8c\x83\x8fi\x9c\x8dw\x04\x13\r\x1fP\xea\xa6\n\x94\xc3\xf3\xcfvw\xe0\xa5R\xcaf^\xf5u\xceU\x85\xd0\xb3]\x85\xe8y\x8di\xcc\xd2.j\xc7\x97G\x1f\xd8>L\x18\xd1\xba\x04y\xd6\x83R{y\xc4aqB\x0c\xc8Rm\xb7=\xf6\x0e\xc4\xa8\x98Y\xe5\xd6\xa04\xf7c\xc9a\xd5\x07\xca\x11\x80\xcex\xcbb\x97#2\xec\xf3\xca\x03\xf7\x95\xcb\xc9\xd3=\x8ed\xdf(\xd2Y\x16^TiJ\xa5\xa0\xaa\xb9\xb3q\x90\x9f@\xb0\xb0\xe1\xc4l\xa3`C\xcd\xe5\x864\x064/\xd0%\xd4\xce\\\xfa\xd0P\r:\xb6x\"\xa8lsK\x06\xcb\xc2x\x83\xb7[\xf4.d\"\xf6\x02Q\xf8X\xf1\xf8g\x1cc\x03 R\x1b\xa7\x15\xbc\x97\xb6\x0f\x7f\xd0\xf7\xcb\xea\xfc:s\x1ay\xdf\x19\xdd\x12;\x02T\x8a\xf3\xa2\x84q\x04\x9bi\xaf\xc9\xe9*\xf3\x98\xe1#\xa1\xf9\xe8\xb0\nl\x8c\x12\xee\xc1\xcfH\xa3\xb3'K\xf4Ot\x19\xacY\xd0?=\x90\x0bV}\xf3+\xc8;l\xb2\x00\x14\xde\x04\x7f\x15\xed\x1eP\xc1-@\x84\x17\x7f\r\x95\xf59\xf3K\xbb\xb8\xa8Y\xe7\xc6\x976\xb0g\x04\xfc\xbe\x15\x9a\x9d\xb6\xa2yfW\xb1Y\xab?\x8f\x9c\xe3\x94\x07\xa8xP\xe5\xbe\xb8\xa3\xe9\xf9c\x88\xda\xb1\xc4\xbd@\xab\xdfe\xb0R\x99\x85y\x808\xdf<\x99\x1c\xd8\xc5\x00\"\xc3\xfd\x92\xf5\xd9\x91\n\xdd.a\x11\x9a6\xe3\x15=hyB\x96\xad\xbe\xf6\x84\"\xf2\xa0 \xa1Ux.\xb2\xc3\xba\xcc\x14x\xf0mK|\x1c\xd9\xd5m\xba\xe8\xb3C\x1di\xd3\x8f91\xaf\xd5\x8e\\\x0c\x19BM\x13c7\xc7\xed\x1c\xf7{JBy\xb6i8q\xcdT~^\xce{\xef\x91$\x85\x883\xc2v\xf1\xb0\xf5vS\xa7\xe0\n\xc5>MTc\x9d\x7f\x01!\x14\xf3x.\xee\xbd\x10#o\x18\xba\xdc\xf9\xf1\xdd\xc0.\xf3\xe3p\xb5`\xd7\x97\xe79\xc1\x8bP\xf4\xce\xc2\x1c\xfa\xc1\xa94\x7f\x1e]Q\x7f\xfa\xdf>\xa7 S'\x8e\xe8.\x8b\xc6y\xa1?\x1c;\xac'\xd00\x0cP@\xe4R>\x06\x15\xb5\xb4\xce\xe8\xdc~\xd4\x8bI4\xf6+\xe5\x82\x1f\xed\x04\xa7\xb8\x9a\xa9\x8a\\\x18\xc6z\x08\xc9\"\x97SE(\xa4KH7<\x8c\x06\xad\xb6\xe45\xf1\x0c{\xff\xad\x81\xe8\xf9\xb6\xe7\xc5\x90\xda\xb9\xea\x05\n\xd5\xd2\x0b9\xcb\xc9\xce\x89\xe0AT\x1c\x0b\xb9]\xb0\x07\xcd\xddWe)B\xb39\x9f\x9a\x0b\xce\xb4<\xa2\xef=\xd0\xc5\xfb3\xf6B\x9d\xd6\xb1\xf68\xff\x16\xd19\xc63\x81M\x89\xf0\xf67\x9a>(gzO\xcdt\xc7\x91\xe3\xbd\x81\xcc)\xa7\x14\xba[\x99\xcc\x92\xbb\xfa\xce\xa1\xd0n\xaa\x91b\xad\x1cb\xfb\xc3j\xda\x9f\xf4\xcf0\xb7@\x8e\xf5{\x14\xedU\xbc\x1d^\xeb\xe8v\xb5R\xc7T\xadR\x04iP\xf5\x7f\x9c\x0e\xf9(w\xd1\xa39`K\xea\xff\xe5\xb4\x7f\x90D\x0e\xf8\xc7\xeb\xc5q\xe8\xa5=\x94\xf9p\xca\xa0\xcf\x01\xeb\x8f8\x87\x00y\xfcm\xdd\xcff\xb8N\xde\x02Lv\x94\xeb^$\xc8Q3\x90g\xf1nMmC\xe31\x81\xb5\x10\xcb\x16\xab>\xef\xf3l\xe5\xc7\xc4>x\x88\xb8\xb36\x1be\xa41q1}^\xf1i\xa4\xde\xff\x10\xc1\xaaJ=\xa0w\xdb\x07R\xd9N\xed\x87\xb5\x04\xa8\xf2we\xf9\xca\xbc\x14\xf5\xb3\x14\xef\xf8\xc9\xcc}\xcc1;\xba\x95\x9d\xe5\xc2[#\x86\xbbJ\xa1\xa0Z\x04\xd11\x00\xe8\xbe\xade\xb6\xa3\xfaaG\x98\xa5Ad\x81#q9\x03d\x9fr9\xdf\x12y\x1fP\x8d\xa5\xd3XYA\xd4\x8c4cA\x8d\xa1\xc7]?6\x176\xa0\xc40\x1c\xd0/\x9an\x97\x1fUW\xac\xb6\xc5T\xbf\x15K\xac\xedoz\xd1e\x83tc\x99\x8f\x93\x108{\x0e[\x82M\xa1\x04\xd4\x1b\x8b'\xf9\x14\xf1\x13\xa4\x16\x83\xc9B\x9f\xaf7\x9b\x04\x9b\x15I>\xd2I<$$|\x823v\xec\x0c\xdd:%\x88e\x1f\x9ap\xa9\x97\xf79\x14\xbe=6t\x99\xc4>@}w=dn\xd5_\x90\xa3C\x91\xc5'\xd1\x8f\xaf\xbb\x05\xc5\xe8\xa2\x80\xf03d~\x0c8\xa9\nm!I\xadvX\x0f#\xdd\x0b!\x0eq\xbe5tP\xfc.\x16\xe8D\x94A4\x87\xa4\x17Y\xee&\x1f\xaae\x1d\xd3MCAG\x1dg\x82|}\x8e\t.\xdeuO\xd1B/\xe3~\xc5\x88\xa6\x156'\x07\xe2\x06\xb7\x07.\xfb\x8f\x1d\"3ju\"7\x13R?\xa3f\x16\xf4\xdb\x0c\xbe\x8b6\x8b\x8a\xaf\xd2\xa6\x9dm\x8fUg\xbb\xb3M%\xff\xcaG\xb2w\xf2\xec\x03\xb9^?\x98Xeiyh\xe0\xe1\xb0|\r\x1ax\x1a\xd4s\x03\x7f8\xfa\xc7qKk\xb8\xb5`v\x1e\x81\x10\xbe\x81\xff\xa9,\x95X_r\xd5\n\xe5\xd4\x98k\x03\xd9R\x9f2|\n\x85\x82!&R\xa51om\x97\xce_\xd64\xfe|\x92\xc0\xb4\x95e;@\xd1)\xdb\xf0n9h\xb8$*N\xe7\xcc\x05\xe1@\x136vs\x1a\xab_\xaed\xf6\xae?S\x1c\x9f5\xdb\x03\x04\x1c\x11\x8b\x97\xa3\x12-\xff\xdao\xd5\xa8!=>|h\\BT]\xd9\x93\x7fK\xfa\x07\x9ch\x9aa\x9bX\xa2X\xd6\xb7)D\xfcs\xc5P\x94\xfc\x05\xb2\x05\x04\x96\xcc\xaf\xeb\xe4\xd2g\\\xbf\x0e,\xfe\x012.{\x00[\n\x93\x00\xd2r\x96ZO\xe3-\xbc\xdc\xe3\xcc\xf7P\n\x19\xd4!x\x0b5\xa9\xe2h\xc7\xce\xb8\xa2\xb3%\xd6<\xd0\x94\x98\xabh\xd1w\r\\x!o\xa1n\x91\x12\xacT\xc3\xa9&Y\\!\xcb\r|t\xe1W\x92E>\xce\xc2\x95\xf0\xcc\x1c\x02\xbbR\xf5z`\x13\x1bh\xbc\xe0?\xd5D\xd3\x1a\x94\x01^N\xaa\x87\xa0\xd2\x19\xa8\xbc\x94c\x93+\xc2\x90\x01\xde4\xb5.\x1a\x05\x91\x18\xab\xb8\xf1\x06$i\xf3\xe41\xca\xf4\xa58\xac\xe9D\xd5\xea\x19\x7f\xf0\xcb/Q\xceWl\xc8k\xbe$\xc2'\x0b\x7f&\xfa\xe5\xc8\xa4\xd6\x0f\x19U9\\\xcb\xa8\x15\x0b\x89\x8cD\xd0\x13\xbe\xbd\xfe9\xf7\xea\x08\xc1\x17\xa3\x91\x97\xaf\xdbN\xfa\x0c\xabV\xdb\x19\x05\xc7\x8ei\xd5\xbe\x83\xb1'\xdf\x96\x03\xa5_\x9e\x0f\x0b\xf1\r\xec\xfb\x0cp\xa3\xfd|\xf8Lb\x80\x98B\xc2\x98\xf3\x91sx\xbe\xcc\xb9\xc1&+\x98Z/\x07\xa1Y\xfd\xedy\t\x9c\x91\x8d\x12\xe7\xf2;\xa3Z,\x99<\xce<\x17\xcfG#\x16\xf1\x9f\x81y \x18u\xea~\xed\x9594\x8e7\xcc\xf0\xb6\xf2#mA\xb0~\x1d&\x00\xa1\xaa\x99P\x80\x1aSs\x01\xfe'Kbr\xebts\xb0\xe7\x08\x93CWW\xbeA5\x9e\xd5B0\xf2\x863aV\xea6\x827\x95\x03\xd9\xb0Di$u\x82b\x98\xf1\xd5\xe1\"[iTVf\tFo36\xb2K\xd0\xb3\x8b\xd0\xe0\xb7~\xb9\xe2\xd9\xf3r\x18\xdf\xe8\x1f\xcaP\xf7:Z\x1d\xdd\xac\xd5\xf4\xbc<\xba\xce\xfd\xf5\x106Z\xd0\x12n\xab\xdc\xce\xc4\xbcz\xf1\x7f\x90X\x8e\x9b=\xae!Y\xcf\xc6\x87\x94\xdd\x91\xae\xdcD\x06\x0f:\x95+y+\xa7\xff\x01\xdc\xb6?'\xcf0\x17\xe6\xa1$NA*\x9cU\xe9sr\xbb\x98O^\x10\x94\x84\x8b\x11\x10\xad\xf7\x89\xd6c`\xd3uX\xb8\xdd\xc7\x86\xb4\x8d\xb7\xed\x1b\xbad\xb1i\x05\xfdt\xa6I\x8b\xbf\x9cw\xf4\xcc\xec\x92\x92\x18?7\x9f!\xfdHk\x90-\xa5\xbd\xdb\xe9\x11\xb6Pp\xe2\r\x16\xc6\xd1\x89\xf6y\xa0|\xd5\xcc\xf9\x99gq\xf3\xb1\xdc\x88kf`f\x8d[\xa8Wx\x8d\xe1\x07\xfdR\xeb>RF(\xd56\x16\xc8\xc4\x9b\x1a/uM\xefe[\x9d\x1b/9\x90\x8cY\xa6\xe1\x04K\xe0:\xd8\xa2r\xde\xc4\x9b\xad\xac\xe6\x9d(\x17\x81\x8f\xc9\x11\xf6.\xb5r\x82\x9f\x83\x827\xc8\xc0\xa0\x9ae8\xb4\xadz\x1d\xe4\x92\xd2\xdb6\xe4,e&\x98\x7f\xa5\x9c\x02\xdd\xb2\xad?\x95iq\x87\xcf+\x10\xfczT\xcb\x90xA\x13Q\x9ar\xa4\x0c{\x02\xb3p\xc25\xf0~\x16\xa4a\xaf\xb91\xd2\x94X\x1a\xbdX\xc4J\xec\x0b.o[\x8a\xd8\x0f`\x97%&\xd8\xd5\xda\xb3\xd0h\x14\xa6\xc9L\xb3\x84w\xe3\xec\xcfV,\x02\x04,,\xbc)\xec\x9d\x9bs\x1cn\x8d\xdb\x8f\x84o\x19\xb53)\xf6\xf2\x97\xb2\xee\xa4\xb6\xb6a\xdf\xa3\xaa\x83\x9f_6q\xec~\x87\xaa1 \xd8\xc5\xe1 {\xfdv4^K\x17\xe1\xb5dg\xa4\xf2\xe9K[\x80)\r\x07\xb9G%\xb7\xcb\xa3\xba[\xbf\xbe\xdfV\xb0\xd7>4\"\xc1\x11ph`[\x1a\xa2\x10\xa0\xb6z\x0e\xbb\xda\xc8\x8e'\xe6\x9f\xa7|\xdc\x1c:1s9\xf8l\xaa`\xecx('\r[ \x1f\xf0\xd7\xa7\xd7\xa1^\x84\xfa\x0cz\xfd^\xae\x8d,\xffub7\x84\xc4\x86\xa3\xea\xc2\x01\xef%\xb5\x84\xadrl\xdd\xdd\x88o ?T&|e\xcf\xbfbI5\x0e\xdcR\x06\x07\x04}\x9c\xb6t\xdcf\xd2\xee\xdfZb\xd7Y\xc0u \xdf\x7f\\\x02\x03@\x18\x01K\x9d\xa6A\xe5!\xb7\x14~\x10\xd1{\xe6,\xbe\xd3\x87u\xd5\xe1/\x07\x197\x01@\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0foCs\x1e\x13}0=\xfa0[\x81h|\xf9\xeaR\xa9\xe3\xf4(\x8c\x018\xaf\xe9\xd0\xa8,\xd4b\xe8A\xa5\xb1q\xc1.+y\xe3\xff\xa8$\x12\xaf\x89\xa7\x9ams\xe6\xcd\xe8\x11u\xff\xe6p\x8a\x8a\xe5O\x08\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f2\x91\x88\xc4\x01\x19\x08/H\x84\xd20_V\xb7\x15\xaf\x90R\x1a\x1b\x16\xcd\x84\xean\xe6\x9a\x89\xc3H\xf0\x9c\xbd\xc3\x95\x18\xf90\xc0\xd2P!fA\xa1\x82\xb6\xa5Wdj\x96\x96\x8c\x1d\x94t\xd6/w\x12K?\xf6\\3\x8c\xa1!\x7f<[\x9d\xcb,\x1fn\xa0\xaa\x8f\xea\t\x90KG\xd0\'\xa7\x9a\x89x\x9e \xf2\x8e\x81\x12\xdd\t\xdf\r\x7fKv\xb5\x89\xa7i\x7fB\x15"\x7f\xe9Y\xa6\xfdY*\x8eX%\xcc\xfcc\x88\xc5d"qH.\xc9\xc8\xe3\xae\xb4\x94\xbdsz\x11\x047\x0c\xf0\x04\x1dWboe\xfeW\x97\xbaD\x81\xa7\x9d\xb4\xfc\x16>\xb5\x05\xed\xd1g\xd5*\xe7\xcf\xd5\xd5\xd4\xc8J\x1f\x859y\xdf\xb7\x1eyu\xc3\xb3\xb4\xca\xa1=8T\xc6B\x17;W\x02\xb9\xdc\xde\xc8\x1f\x88\n\x9b\xb7N\x95%\xce\xc8?\x02t\xfd\xb8\xa2\\\x12\x1d\xd6%7\xe3\xd3l*\x9d\x8f\x93&\xe3?\xc1\xd6\xbe\x14\x8e\xef\x08\xbcM\xb4\xde\xe9\x05\x14)\xa0:W\xebRG\xd7\xde\x1dB\x97Q\xd3\x85\r\xa7\xf0\xf7\xd30\xfcx\xc3ws\x8d\x8e\xf4\x18-3\xc6\xe9\x9f\xe3\x1e\x81\x8a\x99\xdb&6\x8d\xc1\x9d\xc0\x03\xf2\xb7\xbc\xa3\xbd"\xa8\xaf]7\x1a>\x1d\x9cH\xd6\xa8\r!\xa6z\xc0\x117\xb3\x97]PZ\xe8\xdc\xc6\x7f\xf8\x165\xed(\xefQ\xee\x05COb\x15\xbe\x8b\x88\x0fl\xb0WiW\xb1\xffvDdl\xa3\x12\x9cT\\{\xa2\xc3\xad&`\xde\xf0]#\xa3(\xf5\xab\x88\x8ba\x85\x02\xc8\xb3\x1dA\xd20\x0b",\xea\xd3\xc9\xeb?#\x80\xda\xc3\x84\x0fl\xd4\xcc\x1e_m"\xact\x1d\xd2\t:\x1b(\x08\xb6\xed\x92\xe6\xa5\xad\x9b\x84\t@\xa2\x91l\x1a\x90r\x8eTc\x16\xa6\xdd\xfc\xf3#>\x11\xf0\n2,{\x81`\xffa\xf7Jz\x07\x10{\xebh\x90V\xd9j=\xdb"1e\xa2-\xa4\xb4\x82\xc3\xea|\xf8$\x88\x80J/\xa9VU\xbd.\x88\xf7&6\x1d\x18e\xf9\xb7\xb3c\xb2\xe6\x0fvZ\xf4:\n\xb7l\x11\x1f\x00\xcc1\x16\\oQ,\xc4\xd9\xee\xf6\xc4\xf9-\x81n\xf1\xcd\x13DwCg\xbd\xb6\x14\x91\xd92\xb2\xff\x96F&\xc4b\x1el\xb4:\xc5\xbc\xb8\xea@{r\x7f\xf8\x82\xdcgG\xf28f\xc6s\xd5\xa9\x8fH\xe5\x10T{C\xfd\xee\x9b\x1c\x12U\x15 \xf8#\x0f\x95\x85\xcb_\xf5\x1bWO%\x0b\xca\xa1jm\xf2i\xd8\x8e@\xecd`\x93C:\x01w\xbcKrs#\xf5\xd1\x0cp\x1bq\xe3\x95\xf9Q}\xab@F\xb3\xec8*\xfb\x9c\xb9\xa2i\xe4"\xbd\xb1k\x08\xa9\xe0\xe7fH\xf1\xb0-kS\x8bbT\xd4\xe8H\xda\xfb\xe0\x8c\x0b\x8a\x9d\xa4F\x88[G\xe5*\xf6\x84\xb3\xae1\xf6\xc5?\x11Y@|ft\x8d\xa3\x1a\x13~\xd6\x90\xcd\xc8\x97\xaf3\xba\xad\xf6\xdedA\xd3\xae\x08\x00\xf6/s\xd3!dN\xc5\'\xfa\xb6b\x02\xb97\xd2"\x9d\xe6\x9f\x08G\xfb\x05\x1e\xb8,\xe4\xc5\x92\x91\xaaP\xa3\xe4x\x80\xc5\xb0\x14O\x90\x11M\x80\xeb %\xfcs|\xd2\xd5\xf9}\x83\xa6,\x1b\x0bv\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f-r1I\xd9\x9f\xeb2r\xdc\xe0Y\xf8\xe2\xaa\xbb\x94H\xe3e\x89+\xb6\xa4\xca89\x82\x92\x1d\xed\x9e\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f\xe3\xab\xe2\x85P\x08\xd1\xa8\'\x88-\x92e]0\xbf\xa1ai\xa12\xac\xc0hUZ\x82\x98,,\x02d\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f\xad\xf6\\~\xc3{\x8a\\\xc3\xf6@(\x0fN0\x0f\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f\xff\x1dP\x0e\xfeg\xf3D\x9c\xdf\xee\xc2J\xfb\xca\x04\x96\x16\x10\xf10\x17N\x7fL\xf8\x86S|s\x15\n\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f\xf4\xad#UB\x96\xed\xc0qu\x9b\x1cp\x17\x07%\n\x83B\xeb\x81\xabK\x1b\xe59\xa0\x9e\x98\xd73g>\xf0\xfa\xbb\xb7\xbdq\xd1M\x11R\xc3+\x9c\xdaC\xa3H\xeb\'\x04\x0en\r\xf6B\xa5\xb7\xb3\xc5xE\xd8(\xceR"\xc5\x82\x0f\x1f\xa9\x0f\xce\xd9\xd2\x1f\xa5\x8a\xfe\x93\xbc\x02\x18/|\'\\g\xc1\xe0\xf6\xbd\x94\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0fS\xf1\x82\xf9\xdfY\xf3<\xa8\xaf\x18h\xff\xd8\x1b\x19\x19\xcfB\xeb\xe2\xc5k"\x90J4\xe36\x8aI\xe1\xeay\xfa\x1fy\x8a<\xe3\xc4\x8cFIV{\x80\x8f\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f\xf9\x85l\xc3n\x9a=\x9c=\xac\xd0\x9c\x11\x8f\x82\x1cE\xc6\xf3\xe6\xd6\x12j\xfc=al\xed\xbbz\x08\xb5\x13\x9dC\x91ui M\xe2\xbe\xa70\x93\xf7\xa7\xc1Zl5S\x86\x032&k\xd8\xd8\xa7\xdc\xe7\xf3B\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f\xbe\x85\x0cE\x9ep\xc6\x84\x15\xa3\xc4.`\xad\xc9\xb9\x99\x95J\xbd\xd9C\xa5V(\xe9\xcf\x96\x8a\x05@\xcf4dqi\xca\x92\x9f\x1f\x01H\xdb\xfds)A\x94\x9a\x92\xeftq\xa5\xe0\xf9}\x11\xcfkZ\x81tw\x1d%\xc1\x18\x9b\xde\xf3\x88\x18\x88+:\xd7\xd4\xdaW\xf6\xe0\xe1\xcc\xd2\x83a\xea\xdf\xbe\xc6\xee\x82)1\x03\xc3\xb7D\xd2\x8a\x00\x1eO@tVr\xcaO\xadDl \xd7\xa3\xa2\xf4\xda2Q\xce\xaa\x8d\x7f\xd1\xd1\xfb\xc0\xa3>\xb9\xb4\x8eT\xda\xe9z\xd6\xba\xfdT\xb7P-\x02\xa4\xc9\x8a\x1e\x82\xb5\x11\x8e8\xaa\xde/\x84dD\x03\xa6\xf9L\xd7j\x8f%o\xd6{\xf8Gq3(*%\x01\x1d\xea\x8c\xbabe\xe0[^\xa8o_\xee\xa9\tk\xb25\xbb\x07@\x8a\x99\xb9\xbb\xde\xeb{\x92s\xc5z^q\xa9Z:\xc1vtO\x0c7\x9a\x9cf\xdeA@\xb3\xbfX%\x88\x05\x0b;b\x06\x89\x12^,\x82~\x18\x93`\xaeqjy\x1c_\xb6p|\xef\x16>l\x9f\x88\x0fl9\xe9\xed\xcb\x01<\'\x08x\xfa`\xb5\xd4\x14\xab\x10\xb0\xe4\xa2\x8f\x80On\xb7E\xcb\x81\x84\x86\x83\xfe\x15\x8b!Y\xd7\x83*Oh[a\xc1IU\xa4\xb3\x03\xd8,\x7f/\xdd\xed\x8e\xd0\xf2\xbd\x12M\x1eSK\x1d_\x08%\x9b=\xa2\xa1\xeaD\x99mq;HI\xfd.Zq\xec\xa0\x86\x13&\x02\x0bI\xf8\x10\xd6`\xaak\x02\xdf\xe5\xaa\xba&\xfa\xcdP\xde\xe31\x93SN\x0few\xf9\xbf)\x95\x86\xb9~\x83E\xdb\xf2J\x05<-\xddXj\xea\xfeSw\x7f/\x05\xf7)<\x17i6\xb8\xdb3\x13\x8dv\xfd\xa5\xbce\xae\xfd\xc7\xedH\xc9L0@\xd68Z\xce\x1a\x04\x8f\xf8\xeeD`\xad:\x94\xa3\x8c&c[\xc1\x18\xc6s\x7f\x12 \x04\xb5gZ)\xb5\xe9\x8d(\x92\x05\xdag\xa4\x9f\xb8\xcc5\x0f+\xf1\xb9PF\xef\xa0}\xc6B\xea8N\xe8\xb4\xe2\xb1Le\x18\xd7\x18s\xd9m($m\xebM\xf7\xbd1\xac\x8c\x80\xc6\xf8r[\xae\xf0\x16\x88%\x9a\xef\xb2\xe5\x8e\xad\xd0\xc2\x8d\x96\x80\xb6\x00\xd0\x08,\x8c\xe1\r\xc3W\xc0+\xf7\xa5Z\x82\xffi\xad\x01\xe6B\xcd8MN\xb6m\xc6\xa4jS\\\x13\x92\x056\x02\xb3\x98\x8e\x9e\xbbHt\xe3.\x86\x84\xff\x80\xb4\xee\x94?\xbb7\xd7\xc3\xa8KZ\x85Zj\xb7MK\xb3GolC\xba\x128a\xa1a,{P\xfa:\x05L\x16\x0e/\x88l\xcf\xacO\xb7\xd9\x0e\xc7Ur\x9d\xf5d\xc4\xb8\x9a\x82\x18\xdaQ,\x7f9\xc1\x17\xb9\xf4/\x98;U{i\xcc\x83\xe3\xdeuD\xfdU\x06sG\xc7\xeeG\xa2;5\x17\xf0\xf3\x0b\xe8\x01\x97wg(\x14\xa4?\x96t\xa2\xa45\xe3\x1fiAZ\x89O\x19\x06\xdf\xd7W\xc0T\'r\x0f6\xe0\xf9W\xc0\x9aV\xfd\\\x19\xc5yP\x88\xb8pW\xdbU\x98\xa8/\xbb\xb8\xaf\xf8\xe53\r@\xbe\xbc<~\xc8\xff\x11|\x129v\x12\x9c\x8d\x9c\x95#j\x1a\xe9\xaf\xd7\x9b\xd1\x8e\xa12/\x17M\x84\x9c\xcc\x8f\xa9\x14\xec\x86\xcf\x1a\xfd\x1dE\x14]\x9b\x0cc:\xf2\x84D\xaaMiv\x152\xd2\xcbk\x030\x9ajdf\x8c\x06\xecp\xcc3\x92\xaaC\t\x06\xe2RH\xe1v\t\x0fD{@\x04{\xd7\xbd\x8c\xec\xbd\x8e\x16\xbf/@Hrx\xa0E\x16\x907\xaaz\xca\x8fzl\xaah\xb3\xebc\xe9\x7f\xd0\xe7:\x82\xff\xebE\x7fu\xdc\xb5\xf9j\'\x8eI9\n\xae\x98$\xc4\xee\xf5\x80\xbc\xf50O}Z\x0cy\x0f7=\x9cS\xd6\xee\x95\xea\x85T\xe6\x9a*\xcf\x80\xdc\x14v\x8d\x9c\x83\x1f@\xacf\'gi\xb6\xbc\x05~\xe9\xc6\xce\xb2\xd6\xb1\xacy \x13$\xce\xc4\xd1\x02k\x88\xd4\r\xd9A\x9d\x94q\xf2\x06\x15\xdf4\xf1M\xb3\x02\x84\xae\x83}\xdc\xc8\xc3>S\x01\\\x1d\xb0\xfe\x84\xa3s\xa9j\x8a\x13\xd3\xef\x8b\xea\x90x\x87\xb5\xff\xce4\xf9x{\xad\xb8b\xde\xb5\xb5l\xf9\xb3g.\x83\x9dR\xbeD\xd1\x89\xd6+\xe4Xg\x9d\xac\xc4%\xebP \x1f.\xf5\xe78\x05\xefp\x9c\xf3\x0cJ\xb4G\xd4\x1c\x89\x9c\xd3\tj\x97\xcc\xf3\xc6\x85J\xb3\x0f\xaf\xf0\n\xc0@\xe0"\x19\xeb\x81c>]6(c\xcdH\xbb\xb5?R\xd2\xab\'\x01\xc4ug\xf5\xc2\x89CH\xcfK\x8c\xb2\xed\x11\x87_\x16\xff\xc7\xdcwJ\xfe\xea\xee\xc4\x9d\x9f\xb4\xa2:\x01\xd3 \xeb\x95\x84\xadL\xcc\xd9\x12\xa1K\xc7\xc3`&\xba\xdb&\x9f\xf1:f\xe1\x8c\x06\xd1G\x0bw\x84\xaa\xee\x8a?\xcbQ\x8e\x15q\xb7Ey\x8c4\xc3\xb2V\xe5\xc4$\xaf\x05?V\x86\x87\xae\xa2\x96\xa4x\xb2)4\xa5\xe3\x02RZ\xd6_\x8f\xe7U\xe8\x89\xca\x1f\xdd)\x81\x80\xba\xa0\x0c(\xfa\x85\x8a\xac\xa3\x8fH\xb5\xc2\xb8\xd1\x87\x0f\x89[\xa1\x94,\xe4\x05\xc6`\x94W\xc2iS\x01\xa9\xef\xc4=\x92!\rx,\xfeXe\xbb\xb7\n9j \xc4\xaeK\xf0W\xee\nY\xa0q\xd1\xbf\xb99\xc7\x12<\xaa\xca\xfb\xce\x0fCH\xdd\xa7\xb5\r%\xf3\x88\xa7\xd4\xda\xdck\xbe\x186\t\x82\xe8\x99t\xd1\x83\xff\x94+\xa5\xd9\xc0\x8e\xbf\x0c\xf3\xaf\xce\x06K\x86M.\xb8\xaa\x0c\xa5\x0c\xc38\xa8`\x0e\xd9Xq\x10\x007\x99\x81\x9d\xb8O\xeft\xac7\xbcWSN\xaf\xae\x87x\xfb\x82\x18`x\x99\x98\x16\x01AB^\xde\xdf\xa9\xbd{\x93\xdc\xc4\xb8\x9fN\xd5\x8a \x15I\x0c\xcf\n.n\xde\xcbgY\x1b\x1b\xb8$\xb0\xb0\xe4\x13\x1a\x8eN9\xf4Ri\xe3\xdc\x95\xc0\xc8\xc0\xb3\x96\xe2r\x99\xa1\xe9\xfd\xc4\x9e\xfaC\xd3b\x17kT5}\xb1\xbf\xa9\xb3\x03\x186s\xe2\xc7\xc2\xd9\xb25k}\x9fU8\xf9\xa1a\xa0\x994\x029)!\x97\xdf\x87\xda\xcb\x87uO\xfaWTi:\x97$\xfe\xbe/\xb4{\x12\xc3\xa7\n\xe99\x9a,\x08j\x05f\x0f\xd38\xa5\xd9\xc8\x83*k\xc5D\xe3{\x01\xab2\x96\x8c#*\x14|<\xbbFQ\x04\x12\xb6\x1b\xb6\xe3\xf0\xad#\xebg\xf8\xb9\x95\xc1\x98U\xe3u\xa7\x1a|:\xb8\x9d\xa7\x12\xdf\xfc\xa0\x1a\xbb\\\xc8i\x95Zg\xe3Z\xfc\x14?\x17nT\n\x80\xa9Q\xe8A \xfdX\x121E\xd3P\xf4FguK!\x94U\xc6\xda\xed\xd5\x0f\x87\xb9\x7f3\xc3\xd1\x0b\x83c2r6\xed\xa1*\xf8n\x88B\xc4\x94\xbb\x00d\xc1r%6S\xbbq\x02hx\xc1z_p\xd0\x8d\x15\x94\xc0\x90\xa7\x81O\x870ID\xc8\x96\xed\x9cn\xd4\x9d*\x81s\xd3\x89\x8c2<\xad\xac\x0b\x99z\xd8%\x94w\xb0!$N\xe6Gl\xb1k\x87\xf9v\x95e-\x05\x03U$\x1fk\xaf\xc2k\x17\xac_\x0ct\x06\xab\xdd\x040\xc8\xd6O\xd1\xe8\xa2\xf4\xb1\xe0G\x19\x00\x13\x83\x87\xeb\xc7\xd9\xablW\xda\x00\xd4\x9dMmf\xc7Q\xb5\xcf\x1f\x91\x04\x160\xcc\xce{\xd2iw\xed\xcc\x07m\xebc+\x99\x16\x14\x1e\r\x1d\xda,\x98\x16\xdf\xdc\xd4\x92\xd3\xccj5\x80\xf1\xcc\x0f\xf1\xf7C\xe6\x82\xc6\xf5j-\x16\xcc\xfb(#\xe0\'\xb5\xc1\x83\x88\x17\xb2\x9e$\xbd\xa6\x17;\xbd\xf8\xfb\x96\xc4w\x93.QE\xb1E\x97:\x08x\xa04kK\\\xdf\xfe@\x04\x8a\xe9\xfb\xccl\xd6V(\x89\x7f\xde*\xc3\xd9\x92\x8f"\x03\x1b\xea"\xab\x99\x18[G\xc3\x06\x02\xbc\xbbB\xb4,\x05a\x97\x86\x9bw\x91[H\xach#\x01b\x7f\xa5\x7f\xf0{o\x047\x91\x13\xf4\xeb<.,\x9a\xe6\x1f\xb1_\xaf\xd4\x8a\xdbw\xcc\n\xa7|\xc4F\x02\xa5\x8f\x81\xef\x929\xb0\x8c\xea\xfaLw0!\xe8m\xa0L\ne\xfa \xd1\x7f\xcei\x11\x1fc\xfbp\xcbB\xe1\xb5\t\xb2\x02\x83g\xe8` 4zY\xc0zz\xc1\x8d\x83\x0e\x90:r\xafl\x9f\xa5\x95\x1b\x1d-\x98R\xdf\xcfU*\xad\x13\xd28\xa5f\xbci\xa0\xa37}\rpc\x17IC\xa1\r\xda\xae\xd1\x02\xfc\x0fn\x7f&\xd8L\x16\xab\xb8jd\x03i\xf42i\xcd\x17\x85\xf9\xce\xd2\xbe\xae\x9cY\xd8P\xf1\x93\x1c\x06\xc62a\xc2T\x85\x88\xf3w\xfd\xa3\x8d\x82\x94c\xb4\xcaLG\xe5\xb1\x02\xa4S\xbb\xdfC\xe7r\xd7\xe1\xd0\x18\x06\xcecc\x8a\x96\xaf\x1f\xea\xcd\x9bt!\xeaRz\xde\xba\x98\xa7\xae\x01\x9a\xd5\x94\xf7\x07oFI\xe8\x08\xeb\xa7Jm\xf0\xc6\xfd\x9ed\xfb\xdbG\n"\xb5\x93\xf3\\\xa4\xf7\xee^\x8c\xbd\x15\x06e\xda\xbe\xf5\xa1p\x18\x1b6\x914e{\xe2 \xa9\xa2K\x9e\xbc\x7f\xae\\\xceX\xc6_\x0b0s\xb6\xd4\x92\xd9\x85\xfedS\xd4\x03\xafk^FiZ\xeces\xcd\x98\xe1\x11\x9c$\xe1\xcd\x81}\x91\xf9\xd3\x86\x9e\xa78\x00\xa0\x98!\xd7J\x1d\x86\xf4N\x964\x8e\x9f%=\x95\xa3\xd8\xb7z\xfd\xb0\xa5\xc81s\xa1\x9134\x88\xaa\xfb\xb8V*\xe3\xd6\xa7\x9c\x98KK\xdcm\xc5)\xa4\xc0\xc8\x11\xcd\x1e\x19k\x9e\x82\t\x90H\xaf\xde\x08\xbd\xbd\xc0_\x9b\xb2"\x1a\xbd\xd7\x0f\x9d\x1c4\xfa\xa2\xfc\x96\xe0G\xa7\x1a\xc1)\xba=\xcc;_\x84\xcf$\'\x1c9=\xb3\x99\xd1\x061{U\xb8\x1bF5\x9bw!\xec\x8f1\x9c\x8f\xa8\x97\xe9\x08\xc3\x86\xb4\xf0\x98,\xf1\xef\x96R:\xc5\x9c\x91u\xd4_\xc1xy\x1az\xc8\x9a\x10@z\xfe\xaf(c^\xf6\x10B\xc6\xc5-y\x8c\xb2T.\xfe%\x7f\x12iG\xd9q\x97\xf5\xa9\xc8\x0c\x9a(\x1f\xde\xfb\xd9\xdcy\xd8np\xfdt \xd5\xc9Q\xcf\xc3-W\xa9\xeee\xaa\xc3\x17\xd6!\xba\xfaCS\xd2\x84\x86\x0c\xd5QHd@vG\x1d\xd5\xef$q\x85\xfc\xf7\xcb\xca\xe5>V9"PO\xaf]:\xe2\xe4\t;h\xcc\xfe\xd5\x0c\x9d\xbb\xd2\x16\xa1\xa5\x82\x8d{\xac\xefz\xe2\x88\xb6\x19\x8f$\x1eSz\x8c\xe9\xd3b\xc8\x9e\xd15`\x8e\xc3#\xabp\x838\xfc\xf4o\xff.a\xdf\x07\xa8\xa4\xbe\xd3\xd7\x97>=\xc9\xad\xe6\xcbG\t4\xc7\x1f\xd9|\xbc\xe5\xb0\xe2M\x9e*\xfa\xff@0\xe5\xfe\xffU8&\xc5\x0e\x16\xbdS\xc5$\xa7\xe0Z\x89\xaf;\x07\xa2\xf7\xcdB!\x8c\x934\xcf\xf3ez3\x1a\x8b\xe4WT\x9d\x1e\xcc8\xbe\xac\xf2YNJ\x05\x9cd\xdcn\x87J\x93\x94\xe6\x04d\xbd\xec\xa8\xc5\xca\x8a\xbe4\xf4\x0b\xc1\x199Y\xd7\xbdK\xb2\xa3\xe7\xb7\x0e\x03\xdc\x02\x03\x87]\xc1\xb7\x8f\xd9\x1d\xfe\xa1\xda\x1d\x9c\x88`\x14\xba\xcd\xa78\xfb6E\xe2\xabG\x17A,>\x89,\xa8y\xb2\x91\x17\xefcM\xe8x\xb5\xec\xfe2\xca\xcc\xe3\xd3\x7f\xd7\x93"\xd2l\xad\xd7\xc2\xf6.3\x7fJ|\x99\xe5\xabPXMK8\x00Q\xf0\x9a9~\xb6\xfe\x86\xeca"0x\xe3\x86\xe0\xe7\xa4u^\xf3\t\\\xc5^W\xe0\x08\xda:P\x10\xe3\xefc\xcf\x14E\xff\x94\xd4\x08\x0e\xd2\xa7\xe3I[\x99\xfc\\[__\xc1\x84,NB\xf5b?\xec\x01le8\x1a\xd5\xd4X\xa4\xc5\xea\xf2\xb8\xf3\xbe\xd6\xa2\'9x{\xb3\xf6I(<\x0c\xb4\x1a\x10\x14x\xd4\xb1q^\xffm\x12\x88\xea\xfe\xde\xf4\xd4\xd2\xc2Q#\xd23[\xc45\x8a\xa1n9\x8c1\x16vJ\x1b\xcb\x91D\xfdd\xbb\xa6\xcb\nV\xebU\x8d\xea\x94\x91\xf7\x9d\xe6\x9f\x13\xc1\xb8\x1e\xbc\x1e\x8e+;\x87\x9a\xd82\xf8\xc4\xadi\x08\xf9\x10\xd3\x9c\x89\x03\xa8\x96\xff-\x85\x81\xf4e/r`cT_\x97\xb6F\xb5\xb7|\xe0\x16a6/AK\x81\xfe${\xab\t4\xcd\xa0@\x0e\xb1\xb1\x05\xa2\x88\x14"\xe3\xccEb\xd24\xc5\x9f\xeb6\xf4&l\xbf\x9e\xc1r\xf8j#\xa7\x87\xcf\xd2\n\x997\xe5\rhG\xacMRG\x00S\x15hC\x12\x9f\x9b\xf8\xd9\xf9_x\xaa\xb5A\xb9\x84\n:\xc8*o\xff\x0b\xf0\xee\xb4\xe8\xe4B\xcb\xbb\xdbF1\xd0:\xaa\x13\xb9\x9d\x98\x85\xe5\x8bl\xa3\xb6\xd1\x97m\x81\x17\xf0ce\x81@%1\xcc\xefqV\x81\xa6\x81\xcaC\xbb\xdcy\xaea\x0e\x99\x14\xc2\x8f\xd8nT\xc0q\xcf\x98S\x0e\x0bd\x87n\x88\xf8\xa1\xc0\xb60X5\xec`\x04\x01\xc8s$\xb4\xb0F\xad\xc7K\xfb\xec\xc3\r\x86D2\x07\xd1\xc9\x94\xa7\xe4N\xd4\xd7\x14\xfc\x9f{\xd1=\x94V\xc2|\xedb\xfd\x91\x87\x08\xa2kD\xe5\x8c(\xad\xf7E\x15\xd3v\xaa)\'\r\xc2r\x93\xf0Z\xb8\xbe\xbb\xd4\x0e\xa7\x11\x13\xfc\xaaG\xd2M\x05\x93\x1b\xbd:\x01\x0eS13<#\x83\x8ae\x1e\x82f<\x0feg \xae:Z\xf8M\x8f\xa9|\xa0&\xbd\x1f\xe38O\xbe=\xcf\x9fPB\x95\x1cv\x1a\x9aA\x08\xd9\xba\xb9\xd6\xf6eA"\xd4\xdf\xbdN\xfdX\xd5\x1b\x07\x141\xe5\xa8\xbf\x88"\xcfp[r\x9d\xc2m\x87\x0fo\x1bl\xef\xd7\xd1\xc0\xeeH\xb4\xa2\xca\xc9{\xb8\xe8\xa2]95\x89\xfa\xebx\xceQ\xb1\xba\xe6\xa4' # noqa: E501 - with open(self.location / chest_id, "rb") as f: - data = f.read()[8:] # Strip magic bytes - return xor(data, key) + chest_file = self.location / chest_id + + data = read.contents(chest_file, filetype="malicious") + if data is None: + return b"" + + return xor(data, key) def parse_from_log(self, _=None) -> dict[str, QuarEntry]: - self._initDB() + logging.info("Parsing from log in %s", self.name) + if not self._initDB(): + return {} quarfiles = {} # Return the value of a field 'f' + @log_fn def get(e: ET, f) -> str: return e.find(f).text - for e in self.root.findall("ChestEntry"): + for idx, e in enumerate(self.root.findall("ChestEntry")): + logging.debug("Parsing entry, idx %s", idx) chest_id = get(e, "ChestId") path = get(e, "OrigFolder") + "\\" + get(e, "OrigFileName") # Check if an entry is in the vault.db @@ -88,24 +156,32 @@ def get(e: ET, f) -> str: def parse_from_fs( self, data: dict[str, QuarEntry] | None = None ) -> dict[str, QuarEntry]: + logging.info("Parsing from filesystem in %s", self.name) quarfiles = {} # iterating over bigger files, which were not logged to vault.db - for entry in self.location.glob("*"): + for idx, entry in enumerate(self.location.glob("*")): + logging.debug('Parsing entry, idx %s, path "%s"', idx, entry) chest_id = entry.name if not entry.is_file(): + logging.debug("Entry (idx %s) is not a file, skipping", idx) continue if chest_id == "index.xml": + logging.debug("Entry (idx %s) is index.xml itself, skipping", idx) continue if chest_id in data: + logging.debug("Entry (idx %s) already found, skipping", idx) continue malfile = self._getRawFromFile(chest_id) - entry_stat = entry.stat() + entry_stat = parse(self).entry_stat(entry) + if entry_stat is None: + logging.debug('Skipping entry idx %s, path "%s"', idx, entry) + continue timestamp = DTC.get_dt_from_stat(entry_stat) size = entry_stat.st_size From cb6ba8c6f63bb26ffaa4de5a36b3f755eaeaa8c8 Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Mon, 14 Apr 2025 00:14:55 +0200 Subject: [PATCH 20/40] Add new logging techniques to Avira --- maldump/parsers/avira_parser.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/maldump/parsers/avira_parser.py b/maldump/parsers/avira_parser.py index 0878f69..addba08 100755 --- a/maldump/parsers/avira_parser.py +++ b/maldump/parsers/avira_parser.py @@ -1,18 +1,27 @@ from __future__ import annotations -from datetime import datetime as dt +import logging from maldump.parsers.kaitai.avira_parser import AviraParser as KaitaiParser from maldump.structures import Parser, QuarEntry +from maldump.utils import Parser as parse class AviraParser(Parser): def parse_from_log(self, _=None) -> dict[str, QuarEntry]: + logging.info("Parsing from log in %s", self.name) quarfiles = {} - for metafile in self.location.glob("*.qua"): - kt = KaitaiParser.from_file(metafile) + for idx, metafile in enumerate(self.location.glob("*.qua")): + logging.debug('Parsing entry, idx %s, path "%s"', idx, metafile) + + kt = parse(self).kaitai(KaitaiParser, metafile) + if kt is None: + logging.debug('Skipping entry idx %s, path "%s"', idx, metafile) + continue + q = QuarEntry() - q.timestamp = dt.fromtimestamp(kt.qua_time) + + q.timestamp = parse(self).timestamp(kt.qua_time) q.threat = kt.mal_type q.path = kt.filename[4:] q.malfile = kt.mal_file From ed959d28499d5f5c0fe1690a07be740d27d6ad99 Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Mon, 14 Apr 2025 00:15:13 +0200 Subject: [PATCH 21/40] Add new logging techniques to Forticlient --- maldump/parsers/forticlient_parser.py | 36 +++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/maldump/parsers/forticlient_parser.py b/maldump/parsers/forticlient_parser.py index 36ac1e9..3a818e1 100755 --- a/maldump/parsers/forticlient_parser.py +++ b/maldump/parsers/forticlient_parser.py @@ -1,17 +1,42 @@ from __future__ import annotations +import logging from datetime import datetime as dt from maldump.parsers.kaitai.forticlient_parser import ForticlientParser as KaitaiParser from maldump.structures import Parser, QuarEntry +from maldump.utils import Parser as parse + + +def log_fn(func): + def wrapper(*args, **kwargs): + logging.debug( + "Calling function: %s, arguments: %s, keyword arguments: %s", + func.__name__, + tuple( + ( + arg + if type(arg) + not in {bytes, ForticlientParser, KaitaiParser.Timestamp} + else "<" + type(arg).__name__ + ">" + ) + for arg in args + ), + kwargs, + ) + return func(*args, **kwargs) + + return wrapper class ForticlientParser(Parser): + @log_fn def _normalize_path(self, path): if path[2:4] == "?\\": path = path[4:] return path + @log_fn def _get_time(self, ts): return dt(ts.year, ts.month, ts.day, ts.hour, ts.minute, ts.second) @@ -19,10 +44,17 @@ def parse_from_log(self, data=None): pass def parse_from_fs(self, _=None) -> dict[str, QuarEntry]: + logging.info("Parsing from log in %s", self.name) quarfiles = {} - for metafile in self.location.glob("*[!.meta]"): - kt = KaitaiParser.from_file(metafile) + for idx, metafile in enumerate(self.location.glob("*[!.meta]")): + logging.debug('Parsing entry, idx %s, path "%s"', idx, metafile) + + kt = parse(self).kaitai(KaitaiParser, metafile) + if kt is None: + logging.debug('Skipping entry idx %s, path "%s"', idx, metafile) + continue + q = QuarEntry() q.timestamp = self._get_time(kt.timestamp) q.threat = kt.mal_type From d4f10c8a138cefbbe3fa71ff654abda5206971e7 Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Mon, 14 Apr 2025 00:15:23 +0200 Subject: [PATCH 22/40] Add new logging techniques to Gdata --- maldump/parsers/gdata_parser.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/maldump/parsers/gdata_parser.py b/maldump/parsers/gdata_parser.py index c741f6c..af87818 100755 --- a/maldump/parsers/gdata_parser.py +++ b/maldump/parsers/gdata_parser.py @@ -1,9 +1,10 @@ from __future__ import annotations -from datetime import datetime as dt +import logging from maldump.parsers.kaitai.gdata_parser import GdataParser as KaitaiParser from maldump.structures import Parser, QuarEntry +from maldump.utils import Parser as parse class GdataParser(Parser): @@ -13,11 +14,16 @@ def parse_from_log(self, data=None): def parse_from_fs(self, _=None) -> dict[str, QuarEntry]: quarfiles = {} - for metafile in self.location.glob("*.q"): - kt = KaitaiParser.from_file(metafile) + for idx, metafile in enumerate(self.location.glob("*.q")): + logging.debug('Parsing entry, idx %s, path "%s"', idx, metafile) + + kt = parse(self).kaitai(KaitaiParser, metafile) + if kt is None: + logging.debug('Skipping entry idx %s, path "%s"', idx, metafile) + continue q = QuarEntry() - q.timestamp = dt.fromtimestamp(kt.data1.quatime) + q.timestamp = parse(self).timestamp(kt.data1.quatime) q.threat = kt.data1.malwaretype.string_content q.path = kt.data2.path.string_content[4:] q.size = kt.data2.filesize From 4cd969653c80d82e117a4882d09736e43cf1e169 Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Mon, 14 Apr 2025 00:16:01 +0200 Subject: [PATCH 23/40] Add new logging techniques to Kaspersky Anti-Virus --- maldump/parsers/kaspersky_parser.py | 65 +++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 7 deletions(-) diff --git a/maldump/parsers/kaspersky_parser.py b/maldump/parsers/kaspersky_parser.py index 95435f4..dd8cd63 100644 --- a/maldump/parsers/kaspersky_parser.py +++ b/maldump/parsers/kaspersky_parser.py @@ -1,15 +1,39 @@ from __future__ import annotations +import logging import sqlite3 from datetime import datetime from maldump.constants import ThreatMetadata from maldump.structures import Parser, QuarEntry from maldump.utils import DatetimeConverter as DTC +from maldump.utils import Parser as parse +from maldump.utils import Reader as read from maldump.utils import xor +def log_fn(func): + def wrapper(*args, **kwargs): + logging.debug( + "Calling function: %s, arguments: %s, keyword arguments: %s", + func.__name__, + tuple( + ( + arg + if type(arg) not in {bytes, KasperskyParser} + else "<" + type(arg).__name__ + ">" + ) + for arg in args + ), + kwargs, + ) + return func(*args, **kwargs) + + return wrapper + + class KasperskyParser(Parser): + @log_fn def _normalize_time(self, number: int) -> datetime: year = (number >> 48) & 0xFFFF month = (number >> 40) & 0xFF @@ -20,22 +44,42 @@ def _normalize_time(self, number: int) -> datetime: return datetime(year, month, days, hours, minutes, seconds) + @log_fn def _get_malfile(self, data) -> bytes: file = self.location / data - key = [0xE2, 0x45, 0x48, 0xEC, 0x69, 0x0E, 0x5C, 0xAC] - with open(file, "rb") as f: - return xor(f.read(), key) + key = bytes([0xE2, 0x45, 0x48, 0xEC, 0x69, 0x0E, 0x5C, 0xAC]) + + data = read.contents(file, filetype="malware") + if data is None: + return b"" + data = xor(data, key) + + return data def parse_from_log(self, _=None) -> dict[str, QuarEntry]: + logging.info("Parsing from log in %s", self.name) quarfiles = {} + db_file = self.location.joinpath("quarantine.db").resolve() try: - conn = sqlite3.connect(self.location.joinpath("quarantine.db").resolve()) + logging.debug( + 'Trying to open and read from database file, path "%s"', db_file + ) + conn = sqlite3.connect(db_file) + logging.debug('Opening cursor to a database connection, path "%s"', db_file) cursor = conn.cursor() + logging.debug( + 'Exectuting a command with a database connection, path "%s"', db_file + ) cursor.execute("SELECT * FROM 'objects'") rows = cursor.fetchall() except sqlite3.Error as e: - print("Kaspersky DB Error: " + str(e)) + logging.exception( + 'Cannot open nor read from a database file, path "%s"', + db_file, + exc_info=e, + ) + return {} for row in rows: filename = row[0] @@ -55,20 +99,27 @@ def parse_from_log(self, _=None) -> dict[str, QuarEntry]: def parse_from_fs( self, data: dict[str, QuarEntry] | None = None ) -> dict[str, QuarEntry]: + logging.info("Parsing from filesystem in %s", self.name) quarfiles = {} - for entry in self.location.glob("{*}"): + for idx, entry in enumerate(self.location.glob("{*}")): + logging.debug('Parsing entry, idx %s, path "%s"', idx, entry) if not entry.is_file(): + logging.debug("Entry (idx %s) is not a file, skipping", idx) continue filename = entry.name if filename in data: + logging.debug("Entry (idx %s) already found, skipping", idx) continue malfile = self._get_malfile(filename) - entry_stat = entry.stat() + entry_stat = parse(self).entry_stat(entry) + if entry_stat is None: + logging.debug('Skipping entry idx %s, path "%s"', idx, entry) + continue timestamp = DTC.get_dt_from_stat(entry_stat) size = entry_stat.st_size From d1065aa1f3b186ebf72aa1d4e4fa3e21c544d466 Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Mon, 14 Apr 2025 00:16:20 +0200 Subject: [PATCH 24/40] Add new logging techniques to MalwareBytes --- maldump/parsers/malwarebytes_parser.py | 103 ++++++++++++++++++------- 1 file changed, 75 insertions(+), 28 deletions(-) diff --git a/maldump/parsers/malwarebytes_parser.py b/maldump/parsers/malwarebytes_parser.py index 7250a02..d15f1af 100644 --- a/maldump/parsers/malwarebytes_parser.py +++ b/maldump/parsers/malwarebytes_parser.py @@ -1,51 +1,88 @@ from __future__ import annotations import json +import logging from datetime import datetime from maldump.constants import ThreatMetadata from maldump.structures import Parser, QuarEntry from maldump.utils import CustomArc4 from maldump.utils import DatetimeConverter as DTC +from maldump.utils import Parser as parse +from maldump.utils import Reader as read + + +def log_fn(func): + def wrapper(*args, **kwargs): + logging.debug( + "Calling function: %s, arguments: %s, keyword arguments: %s", + func.__name__, + tuple( + ( + arg + if type(arg) not in {bytes, MalwarebytesParser} + else "<" + type(arg).__name__ + ">" + ) + for arg in args + ), + kwargs, + ) + return func(*args, **kwargs) + + return wrapper class MalwarebytesParser(Parser): + @log_fn def _decrypt(self, plaintext: bytes) -> bytes: - key = [ - 0x03, - 0x7A, - 0x55, - 0xC5, - 0xDF, - 0x39, - 0xD2, - 0x89, - 0x7F, - 0xEF, - 0x88, - 0x3D, - 0xC0, - 0x47, - 0xB3, - 0x17, - ] + key = bytes( + [ + 0x03, + 0x7A, + 0x55, + 0xC5, + 0xDF, + 0x39, + 0xD2, + 0x89, + 0x7F, + 0xEF, + 0x88, + 0x3D, + 0xC0, + 0x47, + 0xB3, + 0x17, + ] + ) return CustomArc4(key).decode(plaintext) - def _normalize_time(self, date: datetime) -> str: + @log_fn + def _normalize_time(self, date: str) -> datetime: return datetime.strptime(date, "%Y-%m-%dT%H:%M:%SZ") def parse_from_log(self, _=None) -> dict[str, QuarEntry]: + logging.info("Parsing from log in %s", self.name) quarfiles = {} - for metafile in self.location.glob("*.data"): - with open(metafile, "rb") as f: - decrypted = self._decrypt(f.read()) + for idx, metafile in enumerate(self.location.glob("*.data")): + logging.debug('Parsing entry, idx %s, path "%s"', idx, metafile) + metadata = read.contents(metafile) + if metadata is None: + logging.debug('Skipping entry idx %s, path "%s"', idx, metafile) + continue + + decrypted = self._decrypt(metadata) metadata = json.loads(decrypted) # Open corresponding malfile uid = metadata["trace"]["objectID"] - with open(self.location / (uid + ".quar"), "rb") as f: - malfile = self._decrypt(f.read()) + + malfile = read.contents(self.location / (uid + ".quar")) + if malfile is None: + malfile = b"" + else: + malfile = self._decrypt(malfile) q = QuarEntry() q.timestamp = self._normalize_time(metadata["trace"]["cleanTime"]) @@ -60,22 +97,32 @@ def parse_from_log(self, _=None) -> dict[str, QuarEntry]: def parse_from_fs( self, data: dict[str, QuarEntry] | None = None ) -> dict[str, QuarEntry]: + logging.info("Parsing from filesystem in %s", self.name) quarfiles = {} - for entry in self.location.glob("*.quar"): + for idx, entry in enumerate(self.location.glob("*.quar")): + logging.debug('Parsing entry, idx %s, path "%s"', idx, entry) if not entry.is_file(): + logging.debug("Entry (idx %s) is not a file, skipping", idx) continue uid = entry.name.rstrip(".quar") if uid in data: + logging.debug("Entry (idx %s) already found, skipping", idx) continue - entry_stat = entry.stat() + entry_stat = parse(self).entry_stat(entry) + if entry_stat is None: + logging.debug('Skipping entry idx %s, path "%s"', idx, entry) + continue timestamp = DTC.get_dt_from_stat(entry_stat) size = entry_stat.st_size - with open(entry, "rb") as f: - malfile = self._decrypt(f.read()) + malfile = read.contents(entry) + if malfile is None: + malfile = b"" + else: + malfile = self._decrypt(malfile) q = QuarEntry() q.path = str(entry) From 7f7f56fecfad4154099dbbdb84cd48edf3b857ce Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Mon, 14 Apr 2025 00:16:32 +0200 Subject: [PATCH 25/40] Add new logging techniques to McAfee --- maldump/parsers/mcafee_parser.py | 89 +++++++++++++++++++++++++------- 1 file changed, 69 insertions(+), 20 deletions(-) diff --git a/maldump/parsers/mcafee_parser.py b/maldump/parsers/mcafee_parser.py index ee480d2..3852c0f 100644 --- a/maldump/parsers/mcafee_parser.py +++ b/maldump/parsers/mcafee_parser.py @@ -1,5 +1,6 @@ from __future__ import annotations +import logging import re import sys import zipfile @@ -20,6 +21,26 @@ class McafeeFileData(TypedDict): mal_file: bytes +def log_fn(func): + def wrapper(*args, **kwargs): + logging.debug( + "Calling function: %s, arguments: %s, keyword arguments: %s", + func.__name__, + tuple( + ( + arg + if type(arg) not in {bytes, McafeeParser} + else "<" + type(arg).__name__ + ">" + ) + for arg in args + ), + kwargs, + ) + return func(*args, **kwargs) + + return wrapper + + class McafeeParser(Parser): """XML parser""" @@ -35,10 +56,15 @@ def parse_from_log(self, data=None): def parse_from_fs( self, _: dict[str, QuarEntry] | None = None ) -> dict[str, QuarEntry]: + logging.info("Parsing from filesystem in %s", self.name) quarfiles = {} - for metafile in self.location.glob("*.zip"): + for idx, metafile in enumerate(self.location.glob("*.zip")): + logging.debug('Parsing entry, idx %s, path "%s"', idx, metafile) parser = self._get_data(file_name=metafile) + if parser is None: + logging.debug('Skipping entry idx %s, path "%s"', idx, metafile) + q = QuarEntry() q.timestamp = dt.strptime(parser["timestamp"], "%Y-%m-%d %H:%M:%S") q.threat = parser["threat"] @@ -49,12 +75,26 @@ def parse_from_fs( return quarfiles - def _get_data(self, file_name: str) -> McafeeFileData: + @log_fn + def _get_data(self, file_name: str) -> McafeeFileData | None: # unzip file - if zipfile.is_zipfile(filename=file_name): + logging.debug('Checking if file is a ZIP file, path "%s"', file_name) + if not zipfile.is_zipfile(filename=file_name): + logging.warning( + 'File is not a ZIP file "%s" in class %s.', file_name, self.__name__ + ) + return None + + try: + logging.debug('Trying to open a ZIP file, path "%s"', file_name) with ZipFile(file=file_name, mode="r") as archive: - archive.setpassword(f"{self._zip_password}".encode()) - for file in archive.namelist(): + logging.debug("Setting a passford for a ZIP file") + archive.setpassword(self._zip_password.encode()) + + for idx, file in enumerate(archive.namelist()): + logging.debug( + 'Traversing a ZIP file, idx %s, file: "%s"', idx, file + ) # save files to private variables text = archive.read(file).decode(encoding="utf-8") if re.search(self._re_xml, text) and self._xml_data == "": @@ -62,20 +102,29 @@ def _get_data(self, file_name: str) -> McafeeFileData: elif self._raw_malware == "" and not re.search(self._re_xml, text): self._raw_malware = text return self._read() - else: - print( - f"Error durring unziping zip file {file_name} in class {self.__name__}." - ) - sys.exit() - def _read(self) -> McafeeFileData: - root = ET.fromstring(self._xml_data) - parser = {} - - parser["timestamp"] = root.find("creationTime").text - parser["threat"] = root.find("detectionName").text - parser["file_name"] = root.find("Files/File/originalPath").text - parser["size"] = root.find("Files/File/size").text - parser["mal_file"] = bytes(self._raw_malware, "utf-8") + except RuntimeError as e: + logging.exception( + 'Cannot open a ZIP file on path "%s"', file_name, exc_info=e + ) - return parser + return None + + @log_fn + def _read(self) -> McafeeFileData | None: + try: + logging.debug("Trying to parse an XML file from data in McAfee") + root = ET.fromstring(self._xml_data) + except ET.ParseError as e: + logging.exception("Cannot parse an XML file in McAfee", exc_info=e) + return None + + parser = { + "timestamp": root.find("creationTime").text, + "threat": root.find("detectionName").text, + "file_name": root.find("Files/File/originalPath").text, + "size": root.find("Files/File/size").text, + "mal_file": bytes(self._raw_malware, "utf-8"), + } + + return McafeeFileData(**parser) From 31aa1d9f152976c12ca1ac4b677c9ccc9f0e7303 Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Mon, 14 Apr 2025 00:16:43 +0200 Subject: [PATCH 26/40] Add new logging techniques to Windows Defender --- maldump/parsers/windef_parser.py | 93 ++++++++++++++++++++++++-------- 1 file changed, 70 insertions(+), 23 deletions(-) diff --git a/maldump/parsers/windef_parser.py b/maldump/parsers/windef_parser.py index 18cbed4..87dce35 100644 --- a/maldump/parsers/windef_parser.py +++ b/maldump/parsers/windef_parser.py @@ -1,5 +1,6 @@ from __future__ import annotations +import logging from datetime import datetime as dt from kaitaistruct import KaitaiStructError @@ -11,44 +12,84 @@ ) from maldump.structures import Parser, QuarEntry from maldump.utils import DatetimeConverter as DTC +from maldump.utils import Parser as parse + + +def log_fn(func): + def wrapper(*args, **kwargs): + logging.debug( + "Calling function: %s, arguments: %s, keyword arguments: %s", + func.__name__, + tuple( + ( + arg + if type(arg) not in {bytes, WindowsDefenderParser} + else "<" + type(arg).__name__ + ">" + ) + for arg in args + ), + kwargs, + ) + return func(*args, **kwargs) + + return wrapper class WindowsDefenderParser(Parser): + @log_fn def _normalize(self, path_chrs) -> str: path_str = "".join(map(chr, path_chrs[:-1])) if path_str[2:4] == "?\\": path_str = path_str[4:] return path_str + @log_fn def _get_metadata(self, guid: str): quarfile = self.location / "ResourceData" / guid[:2] / guid - kt = KaitaiParserResourceData.from_file(quarfile) - kt.close() + + kt = parse(self).kaitai(KaitaiParserResourceData, quarfile) + if kt is not None: + kt.close() + return kt + @log_fn def _get_malfile(self, guid: str) -> bytes: kt = self._get_metadata(guid) + if kt is None: + return b"" return kt.encryptedfile.mal_file def parse_from_log(self, _=None) -> dict[str, QuarEntry]: + logging.info("Parsing from log in %s", self.name) quarfiles = {} - for metafile in self.location.glob("Entries/{*}"): - kt = KaitaiParserEntries.from_file(metafile) - ts = dt.fromtimestamp(int(kt.data1.time.unixts)) + for idx, metafile in enumerate(self.location.glob("Entries/{*}")): + logging.debug('Parsing entry, idx %s, path "%s"', idx, metafile) + kt = parse(self).kaitai(KaitaiParserEntries, metafile) + if kt is None: + logging.debug('Skipping entry idx %s, path "%s"', idx, metafile) + continue + + ts = parse(self).timestamp(kt.data1.time.unixts) # Loop through all entries, if they exist - for e in kt.data2.entries: + for idx_e, e in enumerate(kt.data2.entries): + logging.debug("Parsing entry inside metadata file, idx_e %s", idx_e) # Support only 'file' type for now - if e.entry.typestr == "file": - guid = e.entry.element[0].content.value.hex().upper() - malfile = self._get_malfile(guid) - q = QuarEntry() - q.timestamp = ts - q.threat = kt.data1.mal_type - q.path = self._normalize(e.entry.path.character) - q.malfile = malfile - quarfiles[guid] = q + if e.entry.typestr != "file": + logging.debug("Entry (idx_e %s) is not a file, skipping", idx_e) + continue + + guid = e.entry.element[0].content.value.hex().upper() + malfile = self._get_malfile(guid) + q = QuarEntry() + q.timestamp = ts + q.threat = kt.data1.mal_type + q.path = self._normalize(e.entry.path.character) + q.malfile = malfile + quarfiles[guid] = q + kt.close() return quarfiles @@ -56,27 +97,33 @@ def parse_from_log(self, _=None) -> dict[str, QuarEntry]: def parse_from_fs( self, data: dict[str, QuarEntry] | None = None ) -> dict[str, QuarEntry]: + logging.info("Parsing from filesystem in %s", self.name) quarfiles = {} # if the metadata are lost, but we still have access to data themselves - for entry in self.location.glob("ResourceData/*/*"): + for idx, entry in enumerate(self.location.glob("ResourceData/*/*")): + logging.debug('Parsing entry, idx %s, path "%s"', idx, entry) if not entry.is_file(): + logging.debug("Entry (idx %s) is not a file, skipping", idx) continue guid = entry.name if guid in data: + logging.debug("Entry (idx %s) already found, skipping", idx) continue - entry_stat = entry.stat() + entry_stat = parse(self).entry_stat(entry) + if entry_stat is None: + logging.debug('Skipping entry idx %s, path "%s"', idx, entry) + continue timestamp = DTC.get_dt_from_stat(entry_stat) - try: - malfile = self._get_malfile(guid) - kt_data = self._get_metadata(guid) - # all IO errors, ValueError for incorrect structure, - # kataistruct.*Exceptions for constants - except (OSError, ValueError, KaitaiStructError): + malfile = self._get_malfile(guid) + kt_data = self._get_metadata(guid) + + if malfile is None: + logging.debug('Skipping entry idx %s, path "%s"', idx, entry) continue q = QuarEntry() From 20026e5b29cb1f587aa3b4af9827e322028f1849 Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Mon, 14 Apr 2025 00:37:11 +0200 Subject: [PATCH 27/40] Fix mypy and ruff errors --- maldump/parsers/avast_parser.py | 3 +-- maldump/parsers/avg_parser.py | 3 +-- maldump/parsers/kaspersky_parser.py | 3 +-- maldump/parsers/malwarebytes_parser.py | 10 ++-------- maldump/parsers/mcafee_parser.py | 1 - maldump/parsers/windef_parser.py | 3 --- maldump/structures.py | 2 +- maldump/utils.py | 18 +++++++++++------- 8 files changed, 17 insertions(+), 26 deletions(-) diff --git a/maldump/parsers/avast_parser.py b/maldump/parsers/avast_parser.py index e7b2b6a..0f02d46 100644 --- a/maldump/parsers/avast_parser.py +++ b/maldump/parsers/avast_parser.py @@ -5,7 +5,7 @@ import tempfile from datetime import datetime as dt from os import unlink -from xml.etree.ElementTree import ParseError, Element +from xml.etree.ElementTree import Element, ParseError import defusedxml.ElementTree as ET @@ -38,7 +38,6 @@ def wrapper(*args, **kwargs): class AvastParser(Parser): - def __init__(self): self.db = None self.tmpfile = None diff --git a/maldump/parsers/avg_parser.py b/maldump/parsers/avg_parser.py index 0358b11..d09dcc2 100644 --- a/maldump/parsers/avg_parser.py +++ b/maldump/parsers/avg_parser.py @@ -5,7 +5,7 @@ import tempfile from datetime import datetime as dt from os import unlink -from xml.etree.ElementTree import ParseError, Element +from xml.etree.ElementTree import Element, ParseError import defusedxml.ElementTree as ET @@ -38,7 +38,6 @@ def wrapper(*args, **kwargs): class AVGParser(Parser): - def __init__(self): self.db = None self.tmpfile = None diff --git a/maldump/parsers/kaspersky_parser.py b/maldump/parsers/kaspersky_parser.py index dd8cd63..17c1f69 100644 --- a/maldump/parsers/kaspersky_parser.py +++ b/maldump/parsers/kaspersky_parser.py @@ -52,9 +52,8 @@ def _get_malfile(self, data) -> bytes: data = read.contents(file, filetype="malware") if data is None: return b"" - data = xor(data, key) - return data + return xor(data, key) def parse_from_log(self, _=None) -> dict[str, QuarEntry]: logging.info("Parsing from log in %s", self.name) diff --git a/maldump/parsers/malwarebytes_parser.py b/maldump/parsers/malwarebytes_parser.py index d15f1af..135be02 100644 --- a/maldump/parsers/malwarebytes_parser.py +++ b/maldump/parsers/malwarebytes_parser.py @@ -79,10 +79,7 @@ def parse_from_log(self, _=None) -> dict[str, QuarEntry]: uid = metadata["trace"]["objectID"] malfile = read.contents(self.location / (uid + ".quar")) - if malfile is None: - malfile = b"" - else: - malfile = self._decrypt(malfile) + malfile = b"" if malfile is None else self._decrypt(malfile) q = QuarEntry() q.timestamp = self._normalize_time(metadata["trace"]["cleanTime"]) @@ -119,10 +116,7 @@ def parse_from_fs( size = entry_stat.st_size malfile = read.contents(entry) - if malfile is None: - malfile = b"" - else: - malfile = self._decrypt(malfile) + malfile = b"" if malfile is None else self._decrypt(malfile) q = QuarEntry() q.path = str(entry) diff --git a/maldump/parsers/mcafee_parser.py b/maldump/parsers/mcafee_parser.py index 3852c0f..5d59603 100644 --- a/maldump/parsers/mcafee_parser.py +++ b/maldump/parsers/mcafee_parser.py @@ -2,7 +2,6 @@ import logging import re -import sys import zipfile from datetime import datetime as dt from typing import TypedDict diff --git a/maldump/parsers/windef_parser.py b/maldump/parsers/windef_parser.py index 87dce35..58c2c3a 100644 --- a/maldump/parsers/windef_parser.py +++ b/maldump/parsers/windef_parser.py @@ -1,9 +1,6 @@ from __future__ import annotations import logging -from datetime import datetime as dt - -from kaitaistruct import KaitaiStructError from maldump.constants import ThreatMetadata from maldump.parsers.kaitai.windef_entries import WindefEntries as KaitaiParserEntries diff --git a/maldump/structures.py b/maldump/structures.py index 73e0a9f..e9878b7 100644 --- a/maldump/structures.py +++ b/maldump/structures.py @@ -1,11 +1,11 @@ from __future__ import annotations -from datetime import datetime as dt import hashlib from abc import ABC, abstractmethod from typing import TYPE_CHECKING, Generic, TypeVar if TYPE_CHECKING: + from datetime import datetime as dt from pathlib import Path T = TypeVar("T") diff --git a/maldump/utils.py b/maldump/utils.py index 9f09ae0..0490d4c 100755 --- a/maldump/utils.py +++ b/maldump/utils.py @@ -2,17 +2,21 @@ Convenience utils for use in avs and parsers """ +from __future__ import annotations + import contextlib import logging from datetime import datetime, timezone -from pathlib import Path -from typing import Type, Generic, TypeVar, Any +from typing import TYPE_CHECKING, Any, Generic, TypeVar import kaitaistruct from arc4 import ARC4 from maldump.constants import OperatingSystem +if TYPE_CHECKING: + from pathlib import Path + T = TypeVar("T") @@ -75,16 +79,16 @@ class Parser(Generic[T]): def __init__(self, obj: object) -> None: self.objname = obj.__class__.__name__ - def kaitai(self, kaitai: Type[T], path: Path) -> T | None: + def kaitai(self, kaitai: type[T], path: Path) -> T | None: kt = None try: logging.debug( - 'Trying to parse file on path "%s" to kaitai struct of type "%s" on <%s>', + 'Trying to parse file, path "%s" to kaitai, type "%s" on <%s>', path, kaitai.__name__, self.objname, ) - kt = kaitai.from_file(path) + kt = kaitai.from_file(path) # type: ignore except OSError as e: logging.exception( 'Cannot open nor read kaitai for path "%s"', @@ -115,7 +119,7 @@ def timestamp(self, value: int) -> datetime: return timestamp - def entry_stat(self, entry: Any): + def entry_stat(self, entry: Any): # type: ignore try: logging.debug( 'Trying to stat entry file, path "%s" on <%s>', entry, self.objname @@ -130,7 +134,7 @@ def entry_stat(self, entry: Any): class Reader: @staticmethod - def contents(path: Path, filetype: str = ""): + def contents(path: Path, filetype: str = "") -> bytes | None: if filetype: filetype += " " From cc5d4a6755c0b6c950f64ef37c06a955baec27b7 Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Mon, 14 Apr 2025 00:40:35 +0200 Subject: [PATCH 28/40] Fix naming convention in Avira Antivirus Until now, it used function parse_from_log(), however, Avira had no log, only filesystem entries. Now it uses parse_from_fs() --- maldump/parsers/avira_parser.py | 10 +++++----- maldump/parsers/gdata_parser.py | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/maldump/parsers/avira_parser.py b/maldump/parsers/avira_parser.py index addba08..256c567 100755 --- a/maldump/parsers/avira_parser.py +++ b/maldump/parsers/avira_parser.py @@ -8,8 +8,11 @@ class AviraParser(Parser): - def parse_from_log(self, _=None) -> dict[str, QuarEntry]: - logging.info("Parsing from log in %s", self.name) + def parse_from_log(self, data=None): + pass + + def parse_from_fs(self, _=None) -> dict[str, QuarEntry]: + logging.info("Parsing from filesystem in %s", self.name) quarfiles = {} for idx, metafile in enumerate(self.location.glob("*.qua")): logging.debug('Parsing entry, idx %s, path "%s"', idx, metafile) @@ -29,6 +32,3 @@ def parse_from_log(self, _=None) -> dict[str, QuarEntry]: kt.close() return quarfiles - - def parse_from_fs(self, data=None): - pass diff --git a/maldump/parsers/gdata_parser.py b/maldump/parsers/gdata_parser.py index af87818..682ca02 100755 --- a/maldump/parsers/gdata_parser.py +++ b/maldump/parsers/gdata_parser.py @@ -12,6 +12,7 @@ def parse_from_log(self, data=None): pass def parse_from_fs(self, _=None) -> dict[str, QuarEntry]: + logging.info("Parsing from filesystem in %s", self.name) quarfiles = {} for idx, metafile in enumerate(self.location.glob("*.q")): From 1422b604f5edb659edfc2a8085e7514243542fa6 Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Mon, 14 Apr 2025 01:18:14 +0200 Subject: [PATCH 29/40] Rebase: Include changes from main and fix --- maldump/parsers/eset_parser.py | 178 +++-------- maldump/parsers/kaitai/eset_ndf_parser.ksy | 6 +- maldump/parsers/kaitai/eset_ndf_parser.py | 4 +- maldump/parsers/kaitai/eset_virlog_parser.ksy | 259 ++++++++++++++++ maldump/parsers/kaitai/eset_virlog_parser.py | 292 ++++++++++++++++++ 5 files changed, 595 insertions(+), 144 deletions(-) create mode 100644 maldump/parsers/kaitai/eset_virlog_parser.ksy create mode 100644 maldump/parsers/kaitai/eset_virlog_parser.py diff --git a/maldump/parsers/eset_parser.py b/maldump/parsers/eset_parser.py index e18e71c..1d38b68 100644 --- a/maldump/parsers/eset_parser.py +++ b/maldump/parsers/eset_parser.py @@ -15,20 +15,22 @@ from __future__ import annotations -import binascii import logging import re -import struct -from datetime import datetime, timezone +import typing from pathlib import Path from maldump.constants import ThreatMetadata from maldump.parsers.kaitai.eset_ndf_parser import EsetNdfParser as KaitaiParserMetadata +from maldump.parsers.kaitai.eset_virlog_parser import EsetVirlogParser from maldump.structures import Parser, QuarEntry from maldump.utils import DatetimeConverter as DTC from maldump.utils import Parser as parse from maldump.utils import Reader as read +if typing.TYPE_CHECKING: + from datetime import datetime + __author__ = "Ladislav Baco" __copyright__ = "Copyright (C) 2017" __credits__ = "Ladislav Baco" @@ -37,27 +39,6 @@ __maintainer__ = "Ladislav Baco" __status__ = "Development" -TIMEFORMAT = "%Y-%m-%d %H:%M:%S" -NULL = b"\x00\x00" -RECORD_HEADER = b"\x24\x00\x00\x00\x01\x00\x01\x00" -OBJECT_HEADER = b"\xbe\x0b\x4e\x00" -INFILTRATION_HEADER = b"\x4d\x1d\x4e\x00" -USER_HEADER = b"\xee\x03\x4e\x00" -VIRUSDB_HEADER = b"\x17\x27\x4e\x00" -PROGNAME_HEADER = b"\xc4\x0b\x4e\x00" -PROGHASH_HEADER = b"\x9d\x13\x42\x00" -OBJECTHASH_HEADER = b"\x9e\x13\x42\x00" -FIRSTSEEN_HEADER = b"\x9f\x13\x46\x00" - -_dataTypeHeaders = { - "Object": OBJECT_HEADER, - "Infiltration": INFILTRATION_HEADER, - "User": USER_HEADER, - "VirusDB": VIRUSDB_HEADER, - "ProgName": PROGNAME_HEADER, -} -_hashTypeHeaders = {"ObjectHash": OBJECTHASH_HEADER, "ProgHash": PROGHASH_HEADER} - def log_fn(func): def wrapper(*args, **kwargs): @@ -79,128 +60,47 @@ def wrapper(*args, **kwargs): return wrapper -def _infoNotFound(field): - logging.info("Parsing data in ESET led to field not found: %s", field) - - -def _warningUnexpected(field): - logging.warning("Parsing data in ESET found unexpected bytes in field %s", field) - - -@log_fn -def _winToUnixTimestamp(winTimestamp): - magicNumber = 11644473600 - return (winTimestamp / 10000000) - magicNumber - - -@log_fn -def _extractDataType(dataType, rawRecord): - # Format: dataType_HEADER + '??' + NULL + objectData + NULL - - dataType_HEADER = _dataTypeHeaders[dataType] - dataOffset = rawRecord.find(dataType_HEADER) - if dataOffset < 0: - _infoNotFound(dataType) - return "" - if rawRecord[dataOffset + 6 : dataOffset + 8] != NULL: - _warningUnexpected(dataType) - # find NULL char, but search for (\x00)*3, because third zero byte is part of - # last widechar - dataEnd = dataOffset + 8 + 1 + rawRecord[dataOffset + 8 :].find(b"\x00" + NULL) - dataWideChar = rawRecord[dataOffset + 8 : dataEnd] - return dataWideChar.decode("utf-16") - - -@log_fn -def _extractHashType(hashType, rawRecord): - # Format: hashType_HEADER + '??' + NULL + hashData[20] - - hashType_HEADER = _hashTypeHeaders[hashType] - hashOffset = rawRecord.find(hashType_HEADER) - if hashOffset < 0: - _infoNotFound(hashType) - return "" - if rawRecord[hashOffset + 6 : hashOffset + 8] != NULL: - _warningUnexpected(hashType) - hashEnd = hashOffset + 8 + 20 - hashHex = rawRecord[hashOffset + 8 : hashEnd] - # return hashHex.encode('hex') - return binascii.hexlify(hashHex).decode("utf-8") - - -@log_fn -def _extractFirstSeen(rawRecord): - # Format: FIRSTSEEN_HEADER + UnixTimestamp[4] - - offset = rawRecord.find(FIRSTSEEN_HEADER) - if offset < 0: - _infoNotFound("FirstSeen") - return "" - littleEndianTimestamp = rawRecord[offset + 4 : offset + 8] - timestamp = struct.unpack(" Date: Mon, 14 Apr 2025 01:43:06 +0200 Subject: [PATCH 30/40] Fix ruff checks --- maldump/parsers/eset_parser.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/maldump/parsers/eset_parser.py b/maldump/parsers/eset_parser.py index 88e3371..1d18d19 100644 --- a/maldump/parsers/eset_parser.py +++ b/maldump/parsers/eset_parser.py @@ -62,7 +62,8 @@ def wrapper(*args, **kwargs): return wrapper - + +@log_fn def parseRecord(record: dict): return { "timestamp": record.get("timestamp"), @@ -77,6 +78,7 @@ def parseRecord(record: dict): } +@log_fn def convertToDict(parser: EsetVirlogParser): return [ { @@ -98,7 +100,6 @@ def mainParsing(virlog_path): return [] kt.close() - threats = convertToDict(kt) parsedRecords = [] From 60c07a9fff688e7f91f314b7931c1be954b03828 Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Tue, 22 Apr 2025 13:31:42 +0200 Subject: [PATCH 31/40] Move logging decorator to utils.py --- maldump/utils.py | 74 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 59 insertions(+), 15 deletions(-) diff --git a/maldump/utils.py b/maldump/utils.py index 0490d4c..1b5122a 100755 --- a/maldump/utils.py +++ b/maldump/utils.py @@ -7,17 +7,20 @@ import contextlib import logging from datetime import datetime, timezone -from typing import TYPE_CHECKING, Any, Generic, TypeVar +from typing import TYPE_CHECKING, Any, Generic, TypeVar, Callable +from xml.etree.ElementTree import Element import kaitaistruct from arc4 import ARC4 +import maldump.parsers from maldump.constants import OperatingSystem if TYPE_CHECKING: from pathlib import Path T = TypeVar("T") +logger = logging.getLogger(__name__) def xor(plaintext: bytes, key: bytes) -> bytes: @@ -28,6 +31,47 @@ def xor(plaintext: bytes, key: bytes) -> bytes: return bytes(result) +class Logger: + @staticmethod + def log(_func: Callable = None, *, lgr: logging.Logger = logger): + def log_fn(func: Callable) -> Any: + def wrapper(*args: tuple, **kwargs: dict) -> Any: + lgr.debug( + "Calling function: %s, arguments: %s, keyword arguments: %s", + func.__name__, + tuple( + ( + arg + if type(arg) + not in { + bytes, + maldump.parsers.eset_parser.EsetParser, + maldump.parsers.avast_parser.AvastParser, + maldump.parsers.avg_parser.AVGParser, + maldump.parsers.forticlient_parser.ForticlientParser, + maldump.parsers.kaspersky_parser.KasperskyParser, + maldump.parsers.malwarebytes_parser.MalwarebytesParser, + maldump.parsers.mcafee_parser.McafeeParser, + maldump.parsers.windef_parser.WindowsDefenderParser, + maldump.parsers.kaitai.forticlient_parser.ForticlientParser.Timestamp, + Element, + } + else "<" + type(arg).__name__ + ">" + ) + for arg in args + ), + kwargs, + ) + return func(*args, **kwargs) + + return wrapper + + if _func is None: + return log_fn + + return log_fn(_func) + + class CustomArc4: def __init__(self, key: bytes) -> None: self.key = bytes(key) @@ -65,12 +109,12 @@ class DatetimeConverter: @staticmethod # type: ignore def get_dt_from_stat(stat) -> datetime: - logging.debug("Getting datetime from stat") + logger.debug("Getting datetime from stat") ctime = stat.st_ctime_ns with contextlib.suppress(AttributeError): - logging.debug("Trying to extract birthtime") + logger.debug("Trying to extract birthtime") ctime = stat.st_birthtime_ns - logging.debug("Birthtime extracted successfully") + logger.debug("Birthtime extracted successfully") return datetime.fromtimestamp(ctime // 1000000000) @@ -82,7 +126,7 @@ def __init__(self, obj: object) -> None: def kaitai(self, kaitai: type[T], path: Path) -> T | None: kt = None try: - logging.debug( + logger.debug( 'Trying to parse file, path "%s" to kaitai, type "%s" on <%s>', path, kaitai.__name__, @@ -90,13 +134,13 @@ def kaitai(self, kaitai: type[T], path: Path) -> T | None: ) kt = kaitai.from_file(path) # type: ignore except OSError as e: - logging.exception( + logger.exception( 'Cannot open nor read kaitai for path "%s"', path, exc_info=e, ) except kaitaistruct.KaitaiStructError as e: - logging.warning( + logger.warning( 'Cannot read kaitai, probably incorrect format for path "%s"', path, exc_info=e, @@ -105,28 +149,28 @@ def kaitai(self, kaitai: type[T], path: Path) -> T | None: def timestamp(self, value: int) -> datetime: try: - logging.debug( + logger.debug( "Trying to convert timestamp on <%s>", self.objname, ) timestamp = datetime.fromtimestamp(int(value)) except (OSError, OverflowError, ValueError) as e: - logging.warning( + logger.warning( "Cannot convert timestamp to datetime, using default", exc_info=e, ) - timestamp = datetime.now() + timestamp = datetime.fromtimestamp(0) return timestamp def entry_stat(self, entry: Any): # type: ignore try: - logging.debug( + logger.debug( 'Trying to stat entry file, path "%s" on <%s>', entry, self.objname ) entry_stat = entry.stat() except OSError as e: - logging.exception('Cannot stat entry file, path "%s"', entry, exc_info=e) + logger.exception('Cannot stat entry file, path "%s"', entry, exc_info=e) entry_stat = None return entry_stat @@ -139,12 +183,12 @@ def contents(path: Path, filetype: str = "") -> bytes | None: filetype += " " try: - logging.debug('Trying to open %sfile, path "%s"', filetype, path) + logger.debug('Trying to open %sfile, path "%s"', filetype, path) with open(path, "rb") as f: - logging.debug('Trying to read %sfile, path "%s"', filetype, path) + logger.debug('Trying to read %sfile, path "%s"', filetype, path) data = f.read() except OSError as e: - logging.exception( + logger.exception( 'Cannot open %sfile in ESET on path "%s"', filetype, path, exc_info=e ) data = None From c628d2c7ffa1bbd837c453bff5a59ef727cd2a93 Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Tue, 22 Apr 2025 13:32:40 +0200 Subject: [PATCH 32/40] Move logging decorator to utils and use local logger for all the AVs --- maldump/parsers/avast_parser.py | 65 +++++++++---------------- maldump/parsers/avg_parser.py | 67 ++++++++++---------------- maldump/parsers/avira_parser.py | 8 +-- maldump/parsers/eset_parser.py | 58 ++++++++-------------- maldump/parsers/forticlient_parser.py | 32 +++--------- maldump/parsers/gdata_parser.py | 8 +-- maldump/parsers/kaspersky_parser.py | 45 ++++++----------- maldump/parsers/malwarebytes_parser.py | 41 +++++----------- maldump/parsers/mcafee_parser.py | 51 ++++++-------------- maldump/parsers/windef_parser.py | 49 ++++++------------- 10 files changed, 143 insertions(+), 281 deletions(-) diff --git a/maldump/parsers/avast_parser.py b/maldump/parsers/avast_parser.py index 0f02d46..3013ed0 100644 --- a/maldump/parsers/avast_parser.py +++ b/maldump/parsers/avast_parser.py @@ -5,36 +5,19 @@ import tempfile from datetime import datetime as dt from os import unlink -from xml.etree.ElementTree import Element, ParseError +from xml.etree.ElementTree import ParseError import defusedxml.ElementTree as ET from maldump.constants import ThreatMetadata from maldump.structures import Parser, QuarEntry from maldump.utils import DatetimeConverter as DTC +from maldump.utils import Logger as log from maldump.utils import Parser as parse from maldump.utils import Reader as read from maldump.utils import xor - -def log_fn(func): - def wrapper(*args, **kwargs): - logging.debug( - "Calling function: %s, arguments: %s, keyword arguments: %s", - func.__name__, - tuple( - ( - arg - if type(arg) not in {bytes, AvastParser, Element} - else "<" + type(arg).__name__ + ">" - ) - for arg in args - ), - kwargs, - ) - return func(*args, **kwargs) - - return wrapper +logger = logging.getLogger(__name__) class AvastParser(Parser): @@ -43,48 +26,48 @@ def __init__(self): self.tmpfile = None # Cleanup - @log_fn + @log.log(lgr=logger) def __del__(self): if hasattr(self, "db"): self.db.close() unlink(self.tmpfile) - @log_fn + @log.log(lgr=logger) def _initDB(self) -> bool: # Parse index.xml try: - logging.debug( + logger.debug( 'Trying to parse index.xml file "%s"', self.location / "index.xml" ) self.root = ET.parse(self.location / "index.xml").getroot() except ParseError as e: - logging.exception("Cannot open and parse index.xml", exc_info=e) + logger.exception("Cannot open and parse index.xml", exc_info=e) return False # Decrypt vault.db and prepare db connection self.tmpfile = tempfile.mkdtemp() + "/decrypted.db" try: - logging.debug('Trying to open temporary database file "%s"', self.tmpfile) + logger.debug('Trying to open temporary database file "%s"', self.tmpfile) with open(self.tmpfile, "wb") as f: f.write(self._decryptVault("$AV_ASW/$VAULT/vault.db")) except OSError as e: - logging.exception("Cannot open nor write temporary file", exc_info=e) + logger.exception("Cannot open nor write temporary file", exc_info=e) return False try: - logging.debug( + logger.debug( 'Trying to connect to SQLite3 chest database "%s"', self.tmpfile ) self.db = sqlite3.connect(self.tmpfile) except sqlite3.Error as e: - logging.exception("Cannot connect to SQLite3 chest database", exc_info=e) + logger.exception("Cannot connect to SQLite3 chest database", exc_info=e) print("Avast DB Error: " + str(e)) return False return True - @log_fn + @log.log(lgr=logger) def _decryptVault(self, vault): key = b"\x92\xaa\xbc\x89\xef_\x1b\t\xaa\xad5\xf8\xadg\xe9+^Z\xfe\xdd\nt\xf8\xfb\xc3\xa5\x1e\xad\x87\x00\x9e\x16\x82\xec\xdb9(;w\x10\x16\x17\t\xdd\xef\x898\x8c\xff\xbbV\xf7\xa4\x01JU\xd7\xd6\xe2b\xda\x14*\x9c\x8a\x88\xe1\x8a\xb1\x8c5E\xbaZ\xa1\xae}6\x02ac\xa3\xf2`\xaa8\xf1~vv\x07\x1a\xd4\xc2I\xd4(e$\x98\xcf|\xf2\xbd\xc9\x92\x88\xce\x82\xdc\xc9q(i\x9e A\xb8\xea\xf7,\xb9\x9cRbm6\x96fY'\x90\n\xf9\xb5\x9a\x94\xcf\x9e\x96R\xb0\xeb\xdd&f\t\xe0\xe9Ls4\xc5Q\xb6\x1e\xdeHS\x01\xff\x89\xb2]\x93\x08J\xe0\x06\"e\x96\xefg\x8d\x89>\x86^\xd5\xcf\x03(\x08\x9c\xa0(\x8a\xd2\x07k\xc1\x81\xe9\x1a\xd9\xe5\xf3$g<\xf2nR\x13,,G\x07]K\x8dGOKn\xb2\x93\x13ZHR2\x08\x8cu\xac&t\xb3\x08\xba\xfci\xde\xcf\xeb?\xd9\xa0\x97c\xaa\xf8,)\x8b\xe9w\x854o\xa0\xa2U\xb1\x16F\xe6\x13\xda\xa9@\x87\xe0m\xdb\xdb\xef\xb2\x8cy\xa4\xfadX\xddH\xec\x97\x91\xf5\x05\xc5\xa4\xf4&63\xd6\xe8\xa1\x12\xd5\xe7\xb5%\x15k\x16\x05%\x0eZ\x17\x9e\xe2\xb1\"\x1e\"\xc0\x02\xa4\xfb\x1b%{-TI\x8a#\xd2\xdcO\xd5]\x9c\xa3j22\xb8\x01\n\x1f%m~o\xa3TW\xbb\xe8\x14?\xdf\xc2[\x81^\xd4\t\xd4\xb8\xb5\x9dX.\xd4\xf2\x18v\x13E\x88\xacU\xf2\x91\xa9\x0e'\xf2\xee_\xd1\xdb\x95\xbb\x8b\xb5b\x1d\xcb\xef\xf0\n\x01r\xb8D\x82\x84\x18S\x12\rL|\\Vz\x9c\"G4Y\xee\xa4g\xff\x1e\xec\xb2]\"\x04H\x07.P\x83\xd1\xd4\xbfZ\xb6\x0fa\xf28\xe4\xdc\xed\x18\x82\xdf\xae\x90\xef\xfd\xb3>T*\xcf\xf0\xb4{\xbf_8Bg#I\x1f&\xfe*]5\xcf\x1f\xbd\xee\xca6\x80#u\xae\xc6\xb3\xfbp\xb3\x9e\x80\xec\xb2\x8eB0\xb0\x13?\xab\x0e\xad\x0b\x91{\x16\xfd\xa4p\x92~NYK(\x1e\xb9WlW\x1e\x8d\x0c\xa1\xc9d\xd0\xb84\x13\x95\xd0acjP\x96Jf0\x15 \x17\xe1\x08\x06\x0e\x1f\xa0k\x89 \xfe,\xc2\xf1\x14\xfb\xbe:s&\x82E\x15\x80\xb7t\xa3R+\xb2'\x06\x89\xffZ\x80\x14\x98\xff\xe5\xac{\xc3^\xb3\x8d\xa5\x14\xf0\x08s\xd1!w{\x08\tl]\xe4\xc3Ys\xaan+\x1d\x19\xa9\x86M\xd5\xca\x87\xb5\xb4\x13\xf2\x06\x15\xfdKy\xba\x03 \xe1\t]\x0eyS\xc6o*[\xf5\x92JE\x0c\xc6\xa4\xd8\xa3\xb2@\xe1\x05\xf2\xd2\x9d\x9a7\x98wC\x93\x053\xae\xc4mL\xb3e\xe2\xb0\x9f\xcdE9O\xd3x+\xd4h\x9a\x159\x1ak1\xf4\xb5\xddc\xda\xb8~N\x0801P.\xb3D4C\x84<,\x99&\xf48n\xe5\xb7\xb4\x9fP\x10\x02\xb7\xc6P%v\x19\xb6\xa1\xe1\"\xfc]\xfap\x81\xa1\xa8\xc8\\\xc5\x00\x03\xc6)K\xae\xac\xd0\x15\xff\"cj\xc2vTW\x99U\x97\x7f\x88\xa2\xbd3\x87)\x84\xa2\x07M+a\xe5x\xcb\xcb\x13w\x15\xf7\xbeRe\xbe\x9eVg\xd2\xf6\xd2\t\xbb\xc7\xed\x98xW\xb0\x87Z\xf8\xf84\xe8\x87\x10\xcfv\x89;\x8c \xddJrJ\xd1u\xdd\x85S\x8b\x96\xc1\x03\x97]=E\x01\xbc\x93\xa4*\xfe8\n\n\x1d\xc9S\xee\xdcm\xdc3\xe2\xaf\xcc\xb0\xa2\xea[\x1a\x0e>\x1e5SEkM\xee\xca6\x10<\x18\xf0\xbaZ\xa3sy\xdf\xcf\x13D\xac\xbc_-\x0bc}\x87\x8cZ\x8b\x83\x8cw\xc8@%\xb1\x84u\x1d\xcb\x8eE\xe8\x82\x92*\x1e^\xf0\x99N\xce~,e\xf9v\xfc\xa7\x8c{Oc\x08c\x1aFH\xbe@\nr\x7f.\xe6\xfb\n\xfb@\xd7\"\x92\x15]\x00\x8aV\xdb\x01\xa6)3\xee\xcb\xf3O\x91\x9c\x1a\xe3\xbcD\xcdTG\xd0\xfe4\xf0XbX\xfa\x18\x1e\xe8\x01c\xff\xa2~)\xa1\x1cJ\x80T\xbd!x#\xba>w\x07>\x95\x92q\xa4\xd4\xab\xad\x8e\x1c\x87t>\x10\x03\xb1?H\x08\xafx7\x07|H\xfd\xa8\xf6y%\xe6Mp\xe1tIC\xaeJ\xb6\x14\xed\x1b[\xa5\x9b@\x04\xc7zu\xb0\x11\xb6\xaf\x1e\x0f)\x96\x00\xd9\xe5\x8c\x95{\xb5\x11\x02\xf3\xe0m\xc4U\xfc\xc5\x11\xb4\x89\xb4\"\xff\xbb'\xb8a\xf8\xaf\xbf\xea8\xebvG\x1d\x10qq\n\xdd\x9d\xdc\xf51\x0c\x91\x0e\xc0d\x0eUf\x88\x12;\x1fY\x89Kf\xc9\x9c\xbe'YuM\x18v\t;C:4z\xcb;\xeb\x01j\xda\xf8\xa2d\x18\\Y\x92\x0c\x86@\x1a,\xe3\x1e\x14\x96y\x08\x95\xe6RmP\xffT\xb8\x12\xd1\x82f\x80\xfd\xdb!\xd8nky\xe5\xdb^y\xa6`\xea\xe8\xbe\xcc\x91\xab\xb8\rVG\xa7d\xef6k\xb0L\xa2\xe8\xc4^F!\xfc\xcbc\x00X\x01\xcd\xf5*:\x1a#ck\xba\x9b\xdb4\xc9`@\x00;\xdaJ\x15WM\xa9\xec\xa9\xaa\x97\xea\xb0\x044\xb7\xc4*}\xc4y\xfa\xe4\x86\xbe\x83_\xac\xf5>B/s\xa5\xea\x8a?!KhY?\xb2\x18]j\x02+\x93V\xe5\xe9\x9b\x92\xf1-\xcaL\x94\x87\x12\xd3\x9e;\xb3\xa0\xc1 \xb9\n\xa9\x00\xf0\xd0\xc9\xa2\x8fj\x04\xa5\x02R\xf3\xb3\xbd\xe2E\xc5F+\x89'\x1c\x81\xd9&4\xd0Fn\xa6\x16\xa8\xc0\x99a\x15\xb8\xd9\xe5\xf6\x91\xe6\xfcb\xef\xac\xcc\xf3\xf1\xef\xa3\x04\xcc\x867\xc3\x8d\x1c\xc5h\xb8\xf94\x81\x07\xe3B\x0c\xdd\x82L<\x97\xa5\x92\xd3\x0b\x8b\xff\xa2]m\xaa\xc1\x1f\x94o\xf7{\xbaI]\x8a\xf57B\x85M#\x9c\xb1w+\xbd\x95\"\xd9\xe8I%\xe5\x19!\xdbY\xf2\xd6\xf6\xcap\x10\xa9\x1e|*\x96\x7f\x87\x18 Vs\x99g\x19\\\x08(\xc9\xa7\xa7\xafj{d\xcb\x9ap\x87\x13\xa7\xd3\r\xf0Z\x11\x8c\x8e\xf0\x94\x9d\x9c\xcb\x89u\xe7M\xed%\xa12\\\x1b\xaa\xccO\x0f\xaek\xc9\xfb\x0fP\xe4\x02\xd4 d\xf2\xa6\xec\xf2\xb3\x10\x91\xad\x91\x88\xdaaW_E\x10\xb3\x9b\xbc\xd2U\x849\xdc\xb5K\"\xe0\x12\x90u\x9b\xf0o\x9d\xef)1\xf7-V%(\x05\xc3\xfc>\xe9\x8e\xb0\xf4r\xf9\x1b)>5\xd6l\xaa\xa3\x8dg\x14N\x89a\xfbW<\x9bw'\xac|$P<\x8a\xf6\xdf\xce\x97\x816L\xb6+\x83\x80\x01\x07\x98C<\xc5\xefo\x8fi\xd02\xe2fb\x9e\x08\xdb\xaa\xbd\x9ba'&\x81:2\xc4\xe8\xbe\x1c\xc2\x02\xd8\xc4\xf8\xd16d\x82\x00\x1e\x03l\xf1)\x90\xda\x8c\xe9\x93\x91\xc1\xb8\xf7\xd6\xf5*\xc3\xf5#\x93W\x9d\xf1\x97\xa7\x87\x06k\xbf\xa4j\xe7a\x13iW\xd6\x9b\xbf!:\x1e\xfc\xd7:\x92\xba\x05\xc6\xa2L\xfd\xcfv\xce\xd2\xbe\x99\xc9,\xf2\x02\xa2hB\xa1\x14\xa1\xd7N\xa7\x90\xd4~\xac\x83_uz\xb0C\x9ff\x00[;2Hj\x0f\x96\x16\xe6I\xca~\xa5\x1e\xeas\x9bz\xe7!QMZZ\xfc\x01n\xdfl\xd3\x06\xf4z\x08\x0b\xe0\xd9Y\x02\xef\x98\x89\xa8\xcc\xbe\x17\xab\x08\x89Z7{\xa0nY6\x93\xa1\x12f\x8ac\xb1\xb0'\xac\xa2o\xdf\xf9}\xe4\xf8\xae\xda\xf2\xdb0*q\xd8\x87\xd2`\\U\x9bj\xd3\xcb\xec\nG\xb2U\xe0q\xe2\x85\xbc\xaa\xe4f\x0b\xaf\x00\xb7\xac\xc1}ez\xb5\x95B\x91\xdbT@\xd5K\xca\xc293\xa2\xceB\"\xa3\x83\xf9\xebn\x8f\x936\xfc\r}\xac\x00\xac{4\x1b\xceyN\xf3\xa7s\x06~\x12\x0e\x12l\xd3?\xd5\xb4\xc5aw\"[ \xa3\xc4\xc9J\xd0i\xf6\x0fe\xef\xdb\xe2\x9c\xd6%2%?Zq\x0c\xe3\xa3F\x0b(\xc8\xd1\x92\x9b\x1a\x06\xc9z\x12o\xde\x075\xd4\x1e4\xfe\xe3\xf7\t\xf5\xabtPu\x8bxwF\xbba\x8aX\xd0w\x82\xfa\nT?\x03@\x16\xc3>\xdf>\x82\xc9\xdc\x1a\xcf\x7f\xa3\x14\x83N\x95z\x1a\x1e\x1a\xd5f0\xc8\xf2z\xad1?[?Jj\xc8&q7X\x10\xc7w#R\x87\x81\xb2k\xcb\x19LNrq\xc7I7\xfb\xb0\x818\x14x.\xa6\xdcZ!\xe4\x8a\xad\xa7 \x81\xec\x0e\x85\xca\x86\xdd\xe9D\xc6\x1b&M\xeeW{[X\x87\x1d\t\xdcK \xd7\xfd\xceN9\xf5x\x17&\xd1\xa9\xe3q65\x84\x03\xbe\xc8\x19\x91\x9e\xbb(r\xe3h\xe1\xad\xb8\r\xf2\x8d\n\xe7t\xb9y\xf5\xf5\x1fq\x95\x97,\xe6\xe4\xbciQ\xdc\xab\xe2\x87)mh\xb3\xf7)\x82\xb5\xd9\x0c\xfeE\xff\x8f\xdc\x96\xb4\xca\xf1o\\\x19-\xd3\xbfa\x8b\x87\xaf\xd3\x05\xd18\\j\xa5\xd1\x87G\xd4\xe5\xc9\xd8)u\xf0o\x86\xfaQ\xad\x94\xcfK%\x1a:\"o\xcd<\x89b\x16\xd5\xf8\xd6r\xb2\xcdHO\x04[~\x14\xbf\xaa\xf1\xb4T\x8cu\x13\xf9\xf5\xd5\xec7\xa9*\xec\xc2v%\xbb\x98\x96\xb3\xc3f\xeee1\xd1\x7f?\xc0YwD\x04yn&\x92\x01\xd7M\nE\x88'\x08t\xd6\xde\xdeF\xcc\xf0pS\x153}Ut3 \x80\xb6m\xe8\x89\xdf\xcb\xb9h\xe268\x0f\xfb!~\xbaE}>o\xf6p>\xc3\xd5\xf7\xee\xa8\n\xf2\x8c\x81=P\x0f\x1a\xd5\x17\xd9\x16\x19\xb7\xfbi%(\x11\xd1t\xf2/\x90\x91PR$\xd7k,\xb2HE\x1c\x0ek\xe4\xa4\xe6\xc9\x8a\xb0Y\xa3\xa7\x1d=\x01\xe5\x00\xb6n\xa6\xd7A}9(D\xbd\xb5TJ.\x9d\xa2\xac\xc0\x91\xd1\x0bQ-,\x89\x15m,g\xde\x0e\xd9\x11Pa\xc5\xfc\xb7\tRY\xe5\x94\xc1\x01/\xe4\x92x\x1f\xfa%s\xd3\r\xb5\xb2O\x97x\xb0\xb6(\xa5R\x1a\xa7\xa2\xd4\xcd\x99\xfe\x05l\x7fh\xfa\xc7\xcc)\xfc\x1ee\xbe\xf7\xcc\xdb\xc2\xddg\xe1\x9cUL\xd7\xb4\x8e[+.\x03(\x19\xc8\xb6\xfd\xec:\xab6?^H\x04\xbdc\xb2\xa4O\x0bo\xc0(\x19%h\xc1\x87\xf2X\xa2\x05|>\x1fh\xcd\xa0\xd0_\x9f\x88\xfd\xbf\xb8\xd2I\xf1\xaf\xf4\x0c\xb2\x96\x1eq\xd0ss\x11\xf8\xf0\x06\x18\x97\xb5\xb2\x92g\xe7\xe5J{n1\xedUo\xb1\xd9C\xa1/\x8b\xe8R+\x167?\xf5\n\xdd\xac\xf2&\xd7\x07\xf6Nd\xe8U\xea\xecq\x7f\x85\x1a\xbd\xed@\x7fL\xfc\xe8\x9c\x18+\xb8X\xf1\x7f\xee[\x88x\x91\xcd\t\x15N\x16\x98?9\xdf\xd06\xb3\xee\x99\xaf\xddw\x00*\xbd\xd9\xaeQ\x04\xd8S\xd2\xbb\x0e\xa5\xf7\x06%w\xd9\x191\xe2\\\xdb%\x8f\xf7\x9b\xe0\x98\xf5\x1fx0-\x9d\xcb\x8f\xfe\xe0p\xfc\xed\xf1\xa4\x98\xacr|3\x82\xf0\xf8\xfd\x94\xb6\x8a\x14\xe5\xf2\x06\xaf\xee\x9e?\xcc\x10\xbf\xe0\x83\xcb\xdc\x7f\xcf\xc5\x13\xe2\x9e(G\x8a\xae\x84\xf9sJ_ \xbf\r5\xde6\xbf4\xa1\np\x9eC\x8b\xb1l\xa3\xa0PFI\xc0\xac0c\x9f\x08\xc7\x8b^\x1e/9\x95\xda\x8a\x8f \xe1 T2{^\x8e\xa0\xee\x0fc\x88\x82\x82\xafM\xc6\x05%I\xbf\xedb\xaeD\xf8\xfc}\xbb\xd2npd\xd8q\xde\xd6\x06\xf4Q\x80g\x8b6\x92\x8d4\x06'E\"\xa0b\xbc\xde\xc4\xa3#\x9eu\xdeR\x9b\x9aR\xc2\xcb\x04t\xd3\xf9pu\xe8\xb1f\xd4\x8f\x91\xdd\x9e\t\xab\xaa\x10E\xd6\xb4\xec\xfe\xca1\xcfnw.\xcbR\x80\x817\x12\x075X\xdf\xd5h\xc5Q\x1b\xcei\xc4-e\x16D\xfb\xfb]\x06\x7flz\xd8k\xdf\xb0\xd2\x910\x83\tr\xbaa\xee0\xe8V\x84\x03\xf7\x91H\xd5\x82\x9b5Q\xdbM\xb1\xaf\x07\xf0h\xba:\xbf\xd0zAr\xc8u\xaf\ta\x85\x83\xfc=\xa0\xb4\x99\xd0}0NxS\x16:\x15)\x1a\x80\xfc\xf5vf\xc8|\xff4\x8ekw2A.N\xfa\xd6\xd6\x1d\x93\xfc\x7f]'\xb2G\x84pBX\t4\x1e\xbdI\x84\xc5\x8a\t\x1e'W\xd7\xdc\xb2\xb3\x9aJ\x11\x83\xb9\xf1\t(]Z\xc2\xf0N\n\xb4\xeag\xefY+\xcc\x08\xa5\x07\xd3Z3?:\x9d\x96@\x7f\x9d\xc3p<_AD$\xbb\x8d\x1a\xc6=u\xab\xe6\xde\xc2\r\xf0@\r\x1d`?\xc1;\x98\xce\xef~z&\xc2r\xdeg\xaeH \x82\x91s\xfd\xdba\xd9\x1a\xad@\xc9\x01l\xd9w\x81\xb5\xd2\xe3\xc7:\xf1;\xbf4w;\x15\xf4\xe5\x9d\x0f\xe9\x94y\xaa\xa5\x04\x91m\xaf*&\xfd\xea\xe23k\xdd\xc4O%\x18)&~\xd9\xd2\x91\xd3\xc3\xb6\xd7S\xc1\x12\xdfm\x08\x8c\xcb8<\xe27\xfae\xb5B\xbbz\x8aL\xa7\xde2\x89\xc8^\x05\t\x92\x91\x0bp\x14R9Go\xa9v\x05q\xa5\xf8\xb4\"\xa0\xe8S\xfa\xba\xce\x87\xe1q\xccu\xf4S?\xdd\xc7\xc6v\x8d\xbc\x7f`\x04\xbc2\xd9C>8%.\xfb\x951\x17\xdf\xeb\x04![+W2V\xa8\x07]\x8c\xff0\x15O\xe2!AA<\xa5\x87\x06\xbe'p\x8ch\x05HA\x11u\x990\xcf\x96\x8c\xa2\xa3\x9a\x7f\x8a\x08\x0b9\xe2\x19-.\xc83?\xa7\xba\xe5\xc3\xeb\x7f.\x04=\r(FO\x08\xa0\xeae\xc6\xbbCMsP'&Iq\xf9(\xaf\x00\xa1+\x17N\xd1\xad\x0fV9Lp\xdc\x81\xc4\x04\xd1\xc7^1~\xf1\xcb\n\x95\x9bb\x1c\xcdj\xcdm2R\xdb\xe7\xf2\xfeB>9\xd6$\xb7\xeb\\\xbd\xa6\xd4\x0e\x04\xce\xb9\xad\xeeiqz\x8d\xcb\xceJ\xeb9o\xb8\xfa\xd6w\x82\xb2\xdd\\\x13\xdd3\x14`h\xd4\xfe\x1c\x9c\xded\xff\xfe\xc4^\x99]\x10\xfbq\xe6\xd6\xcf\x19gq\x80\x93\x84Ms\xa0\x1c$\xd1l\x8b(\x04\xbf\xcf\xf3\x8b\x08tV\xeb\xa9\xfe\xaeMDh\x1d\x9a\x84\xca*\xb1o\xb7\x81A\x9aj\x96\xf9\xfa6\xfak\x8b\x97\xdb\x1e\x8f\x94\xd7\x1a\x7f\xb7O\x1c\x97E@\nT}I\xdb\xbc\x95}j\t\xe0\xd3\xb9\x03x\x87g+\xb0\xf9P]\x01\x19\xd9\x95\xe6\x877\xd5\xcb`\x81\x12\xfc4\xd3\x9c\x08\xbf\xbd\xff\x18\xb0\xf5\xadG\xe4\x94\xd6\xde\xa2\xd3R\xd7-t\\#\xf8s\x14\xbd\xe6s\x12\xcfk\x0c\xfcq\xbb0\xbc\xf5S\xd2\x95R\x08$\xc6\x97w\x08\xee\x00{\xfdd]\x13UV\xe2\xce\x9a,2\xdb=\x04\x9bg\"\x9b\xea*\x8d\x03\xfdT\x1c\xc8\x8aI\x80\x12\xbc\xa6O\x93\x93\xf5\xaa\xfe\xa8\xd0\x8c\x13\xbfy\xba\xacw]\xaf\xd2\x07\xdc\x97\x86II\x9a\xc1\x08A\t\xaa\x0f\t\xd1\x04+\x8a\xe5\n.\x90\xc2\xc2\xdc\xe7\x9b\xb6\xe3\x1e'\xadc\xe0\xfdx\xec\xee\n\n\xb6\xf2\xdeEC\x18\x95\xe9\xfe\xff\xc0\x1d\xbaG\xdf}&_\x96V%W\xccY\x169o\x9a\xca\x0b\xa3\xf1\x19\x05\x8e\x1b\xbd\x90T\xb8\xc7\x13_3\x1dx;\xcd\xe2\xcd\xc4\xeb\x00/;j B\tf[*\xa2\xc3\xb7M\xa7rs\xd3\x8fc\xa2\xfa%\x05\xe2\xc7\xc4e\x07PoM\xbe\xd4\xa1\xf8G\x98(\xa6\x8b\xcc\xb4i\xbdm=\xdb\xb1\r;\x10bf\x1c\xd9o\x97\xd9\xd1\x01\xa0 #a\x17\xa2\xb4x:p\xf71\x93\x12\r}\x98e\xecq\xb2\x81\xf1o+z\x0f\x9f\xe0\x17\xcf\x940\x84S\x87\xc9\xa0\x05~v\xa92\x18y\xfa\xc7\xea\xc8A%<)\xa8Qo\xc4\xfc\x14\x96\xa2\x85Oq\x86;\x05\xf6\x8f\xab\x16\xf8Dy.@ \xa7\xfah\x1a\t\x02\x82\x01\xdeF\xdb\xac\x19\x0e\xf1\x982:\x883\xf9\xf4\xcb\xe5u\x0f\xa61.\x81\x11\n\x96\x97QK\xfa\x80\rGg\xf8\x80\xdd%\xf0\xb7\x84\x83\x1c\xe8\xf5\xe9\x87\x82aO\x80\xb1?\x9cMu\r\x02\xe17\xa6>p\xe5\x01!\xe9MXi\xa0R\xd9^\x90b\xacm\xc3\x07\xc0]G\xf6\xb3\xfc\x98A\xf3j#x\xd1Z0\xfe8(\xcc(}\xdep\xe4\xbb\x83\r\xd2\xb2\xb4\x0899H\xbc\xbc\xc5g\xb8\x03\xac\xfd\xd3\x07\x15\xf6\x15\xda \x16\\k\r9\xdf\xfe\xac\xf6h\xee\x01$\x89\xca\xb6\xefXpP`c`\xe9@\x94\x80\x10\x1a\xc3\x0f\x94Z\xdd\xff\x8b\xef\xebP\x1dj\x8aE\x7f\xcc4\xf1AbW\x92\x9d\x83Z\xd6\x80\xf7T\x85\n.\xe4\x0b\xd8\x8c\xae\xa4\xdd\x11P\xd2\x93w\x87\xdc\xa4\x00q\x02\xbfiD\xab\"\x80\xd0\xef\xb6\xd70\x1e\x00\xd5\x95\xb4f\x9d\xe4\x10\xfd\xf7o\xe4\x9aGU(\xf6~+\xd6\x17\xb0\x0ejF\x88n2\xd1\xdf5T\xc5.\xd0\xc6\xa5\xd5\xbb\xf3e\x86R\xe1\x8bX\xb7\xd3q\x13\xf3\xbb\xebM\xd2\xa0Y\x1dfG\xf0\xd5\\\xa1b\xcc'W$\xad\xa8>0\n\x07\xa8!Rk\xd5\xdd\x1d\xd0\xf4\xcf\x98\xa1r>}\x95UP/|f\xc7p\x0c\xd4\x17VAWf\x13`\x9e1\xa3\xadA\xb0\x8f)\xf8\x1c\x04\xfbQ\x95\x8c9_y\xe5\xe5\xc7\x06\xa7}R\xf9\xbbO\xe9}X\xeb\x98t\x8b\x19\x94\r\xdd\x1a\xbc\xfb\x01\x9bc\x96\xfe\xbc\x85 \xba\x11\xc8Gw\xae\xfb(\x0fs6\xe0zb=\xedo\x02\x84'S\x8c\x96\xdbH\xa1}\xe3h\xb8z\x08\xbb\xef\x1b\x98\xe8\xafY\x8b\xcb]\xa4\x14\xb8\xef\x90\x0b\xd9-\xadA\x04\x99P\xc3s\xc1\r6\xf3\xb5\xff\xf57z\x94\x1b&\xc07n\x83\x82\xe1\xa5\xe9\x8a-\xfb\xc92}\xba<\x83\x97\x05\x9d\x08\xcb\xe5\x12fdM7\x96Gm\xaaT\x9e\x0b\x80\xff6q\x0fAf\x10w\"9\xac\x81z\xac\x98\x19\xfb\x07sX\xaa\xf3\x08n\x11\xd6\xdc\x1c\xe6\tM@\xb4\xf7\x90%\xdbb\xfd\xe0>\xa1\x03\xd3\x0cx\xfd\xc6\xa4\x9b\":\x83K\xca\x03\xb0\xbe\xd8\x12\xdf}\xe2\xca\xc7\xc8;r\xd7[\x07m\xdfd\xb2\xdb\xd8\xc9\x81\x90\xa7\xe1\xf2\xcd\x1aSZ\xd7ULR\x95\xa1@qrq\x89\xab \xb5\xdd\xfa\x9bG\xd2A\x98\xef\xf8Y\x0b)B,\x01\x9e\xff\xf5 \xb0\xd3\xd0&\xa3\xe7S.\xbb\xbbf|\x80\xbc\xbbG\x1e\x97e.\xaa<\xda\xd5G\xc8h'\xfc\xc0\x9d\x95\x7f\x9b+\x91dVZ\x08\xc9|\x83)\xcf\xc3!\xf6\x93\xff\xbe\x92\xa0\x18\xb4\xec\x10X\xbf\x97N6'<\x8d4\xd5\x7fLZ\xe7I3N\x18\x14bH\x9c\x07](q\x0e<\xe12pg\x85\x17_\xef\xa74\xdf\x8bY\xbe\xbe\xaae\xb3>1\x99J\x9e\x1b\xe6\x05\xba\xfbWzp;\x02XhY\xd4\xd6\x7f\x87[\x0b\xa7=\x83\xacG*=\x90\xc6\x9cZC\x15sH\xf7+\\\xbe\x05_\xde1\x01\x10\x99\x95-\xcbr\xed\x95\xb9`\x7f\xae\xc1\xe3\x0c\xb3|\xb6\x88\xa3P\x96\xa5\xc5\xf5\x89KPs\xac,\x86K\xfb\xa1\x987\xce\xe0\xa0M^\xe4\xae\x9eG65=<\xc9.\x1e,\xe3\xaal9q\x1f\xae\xa6\x1d\xdc{\x90\xb6\xb1\x03\xe7\xa4\x9c\xb7\xa7y\xf1\xe7\xc2\xc1s\x91P Q\x901\xe8\xda\xbe\xb0\xe1g\x9b\xdf\x1bC\xed=\xbaL9\xc7\xf5b\xa6u\x14\xceli\xda\xf4mx\xe78U\x8fF\xe3\xafa\xe9\x00\x1a\xf5q\x15z\x94\x1d|M\x0b\xdfx\x04\xa5\xb0\x80\x0c\xd3+\x97\xaa\xdc\xf5\x9co\xd1\xe7o\xa3\xeaC\xefZG\x93\xa1P\xbc|\xf4%\x8b\x80\xb0t|\xd2\x80X\xae\x8e\xf8]\xc5\xc1\x86{\x06\xe8\x98\xa5\x1d\xf5D\xfb>\r\x0c\x0e\x17\rME\x05\xa1\x87Xg\xdfP\\\xae[\x18\xf5&~$\xee\xb6\x19\x9f\x98|n\xce\xba\xcc\xcd\x06\x88\xfd\xd8O\x9a\xf5\xb3d\"\x13\xa5\"9\x0f\xab{\xc8xw\x11;\x90d=w\xe3\xb1\xd2\xa1\xeb\\'QX\x1b?\xa0=\xb4\xe6$\x17N\x8b\xc1\xd9A\xa8\x92\x97\xe6\x92@\xf3\x07\xfc\xbeT\x97\xecku\xcdV\x90\xf31\xdc\xaf\xc7\xf7\x8e\x81}`\xeew\x93\x7f~M\x80\x91\xf2@\x07\xe3u\x97\xdavF{\x7f\x15\x89\xa6\x00\xca\xd4\xb0\x0e,5\xb9\xd3\xbb\x8bZ\xc8\xba\xc1\xddP+bF\xbe/K8\xc7\xad_\x84\xd5a?\xdadR\xe6.\xdb\x15#\x8b\x9d\xaa\xce\x15\xa7q/\x04\xab\x00\x9dj\x16\xdc\x81f\xae\xf7s\x06\x84,P\xcf\x98Z\x94i\xdb\r\xfb\xc8\xc2T\xe7\x19\xbd\x1a\xc3\xdb\xb1\xd6`KJ\xc4g\xd3\xf4\xa9\x1a\\NW\xc6\xcb*!;\x9e)\x8ej\x1c\xb8u\xb9d\x80\x8bjg\x9a\xec\x18\xa2\xc5>]+,f\xc3\x16\xee\xc8dr\xec*\xcdE\xfe\xd9e;:\xc6\xefN\xc5`\x83\xb7\xb1Y\xea\xa3v\xd5Ng<\xd1\xa6g\xee\xe5V\xe9\x9f\x80\x16\xc8\\\xf7\x04\xe3\xf0\xda\x07\xabe`\x1a\x94\x8c]\x89r8\xf4\xcb\x9a\x0b\x0e(\x9a\xd8e`7s\xaa;8Bbkz\xc2\xe2\xe7\x9d\x95\xdd;A\xda\xd1\n\xd4\xe7\x9a\x01\xcb\xfb^o\x8e\xfb>\x95%s0\xb2\xcc[`\x80\x88B\xf5\xcfT\x83K\x1c\xcf2\xaa\xac\x97\x8f?\xc8g\x0b\x16\xa1BP\xdeZ\x8e\xce\x0e\x07x\x04\xd2\x0c;\x98J\xe6\xb5+\xc8\xa0dT\x9b@\xa3\xa5\xc8\x0c\xe6:\x12\xcfg0X\xb4\xb6\xf1\xf8T\xd8\xf8\x0b9^\xd3\xb2\xe5\xd0\x8d\x93oV\xef\r\x19\x86])\xd0\xd1J\x94\x82L\xa3\xdd\t\xaca\x9b\xc9\x18\x02:?\xf1\xbf\xe78\xba?\xa6\xe3\xd0\xb3\xdeL8*\xd7\x9fSd\x18\x8b\xb9\xa8M\xa1\xdf\x17@\t\x9a@=wZ\xd9~\x9a\xa3O9\xf0\x0b\x93!\xa9+\x9a\x96\xea\x89\xc5!7\xe1\x95L~\xe01\xcdQ\x92X\xfdJM\xf9S\x13\xad\xab\xce\x9f\x1ck\xfcP{M\xa0a\xa7\xd8\x8c{\xaa\xdb\x11>\xdc\x8az(]l\xa3U\xdb\x15+\x9a+\\8\xc7\xbd0\xc1\x98\xc9O\xb0\xfb\x07i6\x98I\x1d\x1a\xe8b\x9bc)\x94x}\xd1y\x86\x94\xe6X\xd4\x1c\xa1\t\x9f\xdb\xe4Z\x16\x8e\xa2Z\xf9\x8boj\xf0\xbd\xa8e\x92\x13\xea\xb8\xf4\x99\xa9]\xf4!\xf6\xbb\x9c\xc8\x1b/\xf5zR7\xb6u\x7f\xf8\x929\xbb\xf5\x12\x02\xc6\x1e\xdbm(>\x94\xe5\x17\xd3\x9c\x03_0\x05\x16\x93S\x90_\xc2\xd5\x00s\xc8\xe1\\\x9dk\x93\xc1\x1e2,\xbc\xe4,q\xf1\xa2\x16\xf1\xac\x95\\g\xe59\x1a\x1d58\x1c\xce\x9d\xa8kp\xff\xc7\x0c\xf6j\x82h\x13V\xdd)\xee\xd9(\x01\xc7eN\xa3W\xb6\xc9\x83x\x92sM\xde}\xa0V7\xdf\xc9\xeb\x0c\xe30\xf0\xe1\xbdOUQ\xba\x1f\xd3\x03\xffr\xd3U;w\x06n\xaf\x89\xd4\x8f?\xe0\xea\xa8\xea\x03\x18\x89\x9f\xdf\xdc\x023!j\x84\xf3\x87\x8e\x01b\x9b^\xf5\xda\x94\xfe\xbba\x7f\xe0?\x17\xc1\xffb\xab\x05\x81\x99\xffH\x19\x07\x91\xfe\xc4\x7f\xf4r\xa63j\x83\xce;\xa9\x08\xb4\xd6\xd7\x99\xf7\xe3sm\xb5\xc9hmAD\t\xbd\x89@\xfd\xeb\x9b\xf4\x85\xcb\xa8\xedG\xbf\xc3o\xaa\xeb\x9cK\xf8\xf9\x08*\xad\xa2\xe7\r\xd0i\x8df\xe6\xf6\xc3n\xbf\xd0\xe9\xe0M\xb4\xf1[lf\x16gS\xa0\x9f*\xcdWI\xa8~\xd6\x10]\x8c_\xb8|\x19 \xc4\x00\x93~\xa7k\x9c&\xbf\x9a\xefhU\xdd}\x14V\xe9\x11\xed\xe2\xf3\xeb\n\x0c\x87e\xb49\xf3eh~\xbc\xe5d\x1b:\x0c\x06\xf9\xffJ`\x96\xd1\x82h\xfb\x94\xe5\x07E%\xae\xed;i\x9e\xaf3\xe4R\x8c\xef\x0f\xae?\xf9Va\xc74\x12\x8f\xea\xd5\xde\x8e\x90\xcd\xbe\x15\xf6\xf1\xa2\xf7\xda8.\xeeR\xc8\xa7\x8a\x1e\x90\xa8-\x97\xf9\x1dl\xcf\x9e\x08\xa8SQ\xab\xf2\x8e\xb8Y\xd5A\x930s\xa2\xe85\x89-\xf5\xf1\xf1\\\xcb\xa9\xe7\x8e\xffn\x9aXut_:`\xeb\xf4\xc1B%{H\xc9\xa2\r\x0f\x1f\xbc\xcad\xfbdI\x1f\x8a\xa7LZ\x98^\xda\xda\xd2\x9e\xe4L\xaeS\xa4PD\x91YT\xcem\x1d\t\"9jepP\x04\x13\xca%\x06\xb9\x96\xf3|\xa5%\x04d\x83\xb5\x87\xe2b\xa5@\x1f\xba\x07\x97\xe8>S\x8a\x82:\x8f\xbb\x0f\xb2\x86\x8a\no\x8bd\xbf{\xe4\xa2\x8e5\xc1\xd5\x8b\x9e\xd0\x87\n\xe4\xd2\xafv\xb9\xe7\xba\xfc\x17\x01\xbd\xcc\xa4Q&Fl\x1cy\x87\xb2\xc7B\x8d\xb0\n\xab\xcdC\xd6\x9d\xe9Wp*\xa8j\xbe\x82\x91\x13\xda\xb1^\xf6\xca\xb7\x14\x85\xb1\x07(AH'g2\x00\x89\xbd\xcb\xf30h\xf8\x1b\xf4\x867\xcd\xfe\x1a\x1d/!\\\x85Y\xd2\xa1\x03\x05\x17\xe6\xd1m\x99l\xb1:\xb1\xadu\x8a\xef\x91H\x81\x81\x12\x8bc\x1e\xc5\x06\x0e\xadMbY:\xf2\xc0\xb3\x1e\xe3\x1d\xd0O\xda\xb81\xccP\x11\x82\x12\xd5\x91$\x7fU\xd2m\xa8\xa0\xbd\xb3\x8f\x9dMfL\xd474\x19\x81c\x81\xb1\xab]WTt?\xc3\xfe\x7f3\x15\xbep\x02:\xaeV\x8e1\x00\x06\x12G\x1d\xa9K\xbc\x93Dm\x8b\xc5\xb9\ta()H\x11\xd0z\xf6\x10\xf8\x9c\x01]W-DM!\x121\t\x01\xdc\xf1n8\xab\x82+\x1b%\x0cG\xf9\xadAt\xfb\xc1\x05\x81`:\xfe\xc0\x17\x92f\x14\x119\x80\xff\xc3\xb2=\x8d\xa5i\x86`\xf1\x06\x81\x1b\x9b\xcau2\xf1\xe5\x82\xe4\xe3\r#u\xae4\xb0E&\xd8\xacy}\xa3\xe7\x0c\x8c\xce\xaaJ\x8d\xe4\xcf+\x04\"U\xb5\xb7\xafF\xaf\x97\x04\x94}\xfb\x88\xdb\xca\xc0\xe2\xd8\x08KU J\x0fe\x16N\x92\x06\xbbr$n\xa1\x0e\x08ed\x946\n0_\xb3;\xb3\x9d\x0c\xce\xc7\x85]\xa5\xf7b\x17\x82\x7f'\x8c{dg\xb9T]N\xc6;[\x9a~[\xcd\xc4\x02\x98+:*\xae\xa7%\xc5{\xc7\x05\xb8\xfa\xc6\xc5|\xe9\x92G\xa4\xb1\xa6G5\r\x94.\xbf=\xc9\xc3\xc8R\x0fa\xb5X*\n\xc1\x11q\xf37\xec\\\xf9_n\x7f\x08\x1e\xffV\x95y1Nx\xb9\xbaIJ\xf9\x14W1\xb4\xdb\t\x01r\x1d\xc4\x1a\xa0m\n\xb6p>/\xae\x05Z%P\x88$v\xa9+\xdd\xa8r\xf7B.\xd4\xd4\x97(\x1a\x14X\x94\r\x0f%WU(\xb4\x10\xdb\x14B.L.\x1a\xca\x184|\x9c*\xca\xa8\x82\xe3\x12:\x1c;\xa5\x83\xe4e\xebp\x12[\xcc\xf1\xb3\xd3a\xd3\xf9\xd8\x1f\x94\xd54\xdeX\xe2a\x9b\xa4tn8\r5\xaaX\x99\x0e?\xf8#l|!\xaai\x0f\x17Y\x98\x85\xc9b\xa8\x1cK\x11H\x05\xaf\x8c\x05\xab\x87pgwX\xe8\x7f\xc9\xd0jU\xd3\x1drs\xfd\x07\x95S|\xd3\xe1\xba\xf7?\x8d\"\xf6px`\x8e\x04\xea \xee\xb8\x15\x9b\x15\xa0\xb9W\x1f!\xbf@\xd6\x85|\xba\xab\xe9w\xa4\xa4\x11&\x8a\x14\xfcl\xe9\x94\x1e<\xdd\x92\xa7>\xf6+\x1a\xf4\xee\xd0\x08x\x1f\xe8s\x18j\xc7BAsi\x9bN\xc5\x87\xd5!\x8f\xe7\xd1\xedQ\x162#H \xcb?\x8a\x8d\xa2(\xbf)`\x7f\xac\xaa0S\xfb\xcf\x15j\xd7FU\xf6\xd4lT\x1b\xf3.x%\xdb\xb1\x12ttBQ\x89\xccF\xd7\xa5\x12\x05\x13\xbcM\x8d\xc3\x7fr\xe2\xfam6\x88\x8d\xaeK\xc2\xb1\xa8\x82\xd1lb$\xa7\xffB\xf8\xa3\xe8\x89:Bpe\xe6\xde\xcf\x91\xe1X\x18\x00%\xb4\xeeTs\x05\x1b\xeb\xe9\xe4\xa1A`\x1e\xf1\x00\xfe\xd7lj\xe3$R\x1b'K\xe48\x14)\x04\x02a\x8c\xe4\xae\xc8\xa5\xfb\x82\xf3\xb3\xd40\xd5vH\xf2\x94\x8c\xd1\xc0\xfa\x8f\xaeO\xbd\xfb\xf3\xdc\xd4\xc25\x81\xb6r\xffD\x113e\x9be\xab\xb0\x1f\xef\xf6\x8a\xbake\xc2\x1f\x93\xfa\xa5\xe9b\xb0I\xeb\xa3f\xa0\x8d\x02N\x88\xe3\xe7f\x01\x0bYQ\xf1LR\x9f\xf9F\x9a\xcall\xf2UN|c\xfek\xb7\x08\x8d\xd5K\x00M)(\xd4C\x11\xd6\xb3\xd1\x19\n\x08xyAb\x17'\n\x08\x19\xaa\xe4F\xbd&\xaep_\xdeV\xdc\x1c\xd4\x02\xb9M\xe9\x08\xbd\xec\xbf\xb4\x8f{\x12\x98\xa6\x10&\xa3{\x92\xd9j\x91zo\xf9/\xcd\x84p\x1e\xc5\xb7\tI\x84\x0f\t\xdc\xb5g+\x94\x84\x82\xc6D\x1f\x13)\xb3\xa0\x8e\x8d\xba\xd2\xc7\xe3\xe9e\x8bS/\xd8*6\xd5w&\x86:\xa6\xe8\xdd\xd4\x929\xe3/\x8b\x8flrj\xa7S>]A\x8a\x12\x9apC\x1c\xca\xf8\n\x1d\x93\xd8\xb7\x89\x7fF\xea\xcf\xbco\xf5T\xbb%\xbb\x12\x04K \x8a.6s\x03\xed\t\xda\xa3\xa6\xc6\x920\\\xc2\x8bm\xa8\x9e\xa0\xa7.\xca\xb1\xdc13\xa0(\x8dP\x12@3\xfb \xb0M\xaf1\xa3\xb8vMb\xab\x88E~\x1b\x81W\xda\xfb\xed\x97?k\x17X>\xca;o\xb3]H\xe7\xf6>\x84\xd5n\xaa\xc8)\xb7\x89\x0f<\x9c\x0c\x0fZ\n\x14\xfel\xcfk\xa0\xba\xec\xf0]\xc2%\xa2\x9f\xb9\x93\xdc\x8e\x7f`-\x08\x7f2k\xad\xc9\x1b\xbd\xc3\xd3\xfa\x06\xc1q\"\x13jR\x9e\xa2N>\x18\xfd\xa4]bb\xc7b\xd4|\xe4\x1b\xa4,\x9a\xdb\x80\xf3\xf7!\x1d5\x8f\x9d^D\xca\x97\x8cCn\x80\x86O\x94\xf5\x8b3\xb5\n$\xe7\xa2\xaaI\x84\xf0\xca\xf3#Q\xd1\xfe:\xb6\xa9\x15\x98\x05\xea\xb6g\x81(\x00d\x15\xef\x87\x80\xd2iU\x96\xe3Q\x9a\xd7\xa0\xc6\xdbJ\xa8\x13\xf7[,:\xe2mQ\x1c{5x\xeb\xd6\x99\x92\xba\xea\xad\xd7\xa8\xa1N\xd6\xb3u\x08G \x8co \xc1\xe2\x93\xe5\xfc0/\xcd\x9d\xb8p\xab\x88\xb1\x80#\x12\x00$\xbf\xc7h=\xf6\xdb\xb2\xff\x02W\x93v\xbf\x867\x06V+\xc4\xe4\xef\x93\t\xac\x0b\xc8&\x87\xd8\xf1\xa4\xf4b\xac\xd4\xa9\x97\xd04\x89 \xbcWK\x03\xc4\x8dOu\x80\xd1\xeb\x18j\xfaXK\xb6\x02\xb4\xd4M\xf7\xce)\xb1\x94\x90;\xd4\xeb\x9cX\xabG\x9fF\xf0\x10\"$\xe9\r\x91\xa64\xf8\x15f\x0b\x86K\n-1\xe2B\xc4\xaay\xeb\x05\xbfm\x0c\x8d\xac+T\xb4~k]v\xe0\xc9\xc8\xa0\\?\xd6\xc3o%g\xa9T\x97\x03\xb1\xa5\x88\xab:\x9c0\xc6\xb8u\x14\xb4=v\x91\xec\x01\xa63\x83\xb8\xea\x9b\xef\x0fQ\x03!p`\x9a\x14\xae\x19\xf2\x85N\xd6\xb4\xb6?f4\xc6\xa2\x89\xa1\xef\xae\x8a>\xba\xfa\xb8\xf4\x9f\xd5\xd3\x14\xeb\xb4:\x0c\xbc\xe9Si\xa8\xff\x19\xb3\x0e U\xbb\x0b\xc8\x8c3\x83Oa\xd4@\x15\xcf\xb5\xda\xbdXMt\x1f\x15\xf9\xbc\x1b\xe9\xd9\x9b\xa21\x11\x9bI\xc4B\xdcME\xe2\xc2\x04\xeaI\xf0?|\xf0\x99V\xde\xafL\xe04~-vg\x15\xbc\xed\xc4\xf63;\xa8\xfa\x1a\x1d\x16\xdc\xf2\xb6I\")\xa0$\xbc\x86B\xbf<\x97\x88\x83\xae\x13\xa7\xb8\xe9\xfb\xc0\xfb\xe3\xbb\x95?\x1fH\xfd\x9ab\x99\xb6|>\x08\xb9_DN(\xb8n\x9c{<\" I]\xd0F7;N\x19)(\xe3P\x80\x7f\xae\x12\xe5Y\xb20S\x90n\x1e\x01\x88}\xcb\xfbXC\x9d\x94F\x1a\x1a5\xda\x85\xc43\"iH\x06\xb6\x82\x00\xdb\xa5\x96\x90\xa4|\xfez\xc4\x9a:h\x04g\x0f\xc9+\xc6\xcac-\x90\x00'\x17\x8e\x0c\xc8\xb8?\x90e\x02\xc3!\x15\r\x03\xc0\xb2\xf5\x17(`\xac!\xdf\xfe`\x92(\xeb\xf3\xf9\x8e\x9c7\x00nGo\x18~\"\xfb\x85\xcb\xfa\x0f<\x93E~\xcd\x80\xa8\xd2\x96\x83!\xb3\x80\xcd\x81\xde\xdc\x9b8\x03\x04\x80^\xbbV\xcce\xe2!#PD\xaf6\xc4\x1f\x92l\x89\xae\xc6\xa6\x12\xf0PY\x9d\x11\xb5\xa0\xca\x14\x8e \xd1\\\xcb\x14\x84\xa9\xdd\xba\x16;\xdc\xe8\x8c\x02\x1e3\xbb\xaef4|!\xc4\xb5K\xa6f[e\x12\xc5\xe73\xca\x00#\x81\x07\xcf\xc6\x98u\x91\x12\x14w\x04\xc8\xe5\x82Z\x1du\x06\x04\xd6\xc2\\\xca\t\xb5\x0cx\xd2\xb5\x92\xac%\x9c%\xe4\x03\x0b)\xb0I_g\x9e\x91\xa6\x04\x01~2q\xf1/W\x90P\xb5\x88\xcf .\x97Y\xda\xd4\x920\xe6\x9b\xb0j \x1b\x16\x0b\xc7\xec\xa5J\x003\xf7D\xf5%\xf2}\x84\xb5\x12\xbe\xb4W\xe8\xfeii\xef\xbe\x1c\x07\xb7T]\xeb\xe2\x18s\xc8\x8f\xc7\xee\xe7r\xd6\x84\xc8\xfap\xfb\xa7\xb2\xf4\xa3G\x9c\xa0G\x98\x9d\xba\"Z\xbb\xcb\xdb}\xd3\x99\x07\xf9\x02\xa3'\xb8 \x93\xafs\x88)\xb2\x0eB\x075\xc9\xa6u2\xd4\x13\xae\x19\x12\x14\xefE\x9f\xb2&\xd6\xfe\xa8\xabY\x0b\x1ac\x18q\xfc\xb8/\x95\xc2#f\x8e\x8b\x7f^e\\ \x0b\x96\x08\xb5\xa6\xd7\xd9[\xfe\x88\x8c\xffM}Z\x13\xd8\xff\x8a\x16J\xa3\x89@-\xdf\x9721\xf7\xfa\xb2\xd2;\x00I\xc9\xb0>\xf8\xd8\xee2\xa3\xeb\xbb\x0b\xe3J\xc8.e\x8e_K~9\xa3\x9b\xe0\r\x8b$\\\x13\xb8\x8f\x1a\x19O\xbb!a\xc3\xff\xec\x85e1\xfc\x98\xff\xcc[\xd9\x07j\x1d\xea\xb3\xb5Z*\xa6g=\xfd\x9d\x1bc\xd20\x88\xde\xa0\xfe\xaf\xca\x08\xa34\xb2\r\\\x01\xfd\x97\xf0\xc3\x81\xd4\xbf\xb66\x0el\x1f\xd5c\x1b\x9d\x96\x06\"k\x9c\xce\x91Iu3\xb9q\x19\xb0\xf5\x08\xcdc.\x04\xfd\x7f\x85\x1d,\xe5Jb\xab#^\xfc\x008\xb9\xe5\xf5\xb94P\x9bk\xa9\xd1E\xbb`\x02O\x9e-8`\xd0\xe3\xe80<#\xcd\x8a\x03\xdc\xfcT\xf3\xc0\xd19r\x81\xfc\x94\x9f\x7f\x95\xab\xad\xaf\xccpN\xa9\xc9v\x7f\xf9\x7fF\x8c\xbc\x00\xf5\x99\xd1u\xb5^s\xa9\x8f\x98(\xca\x187\x9a\xd2c\x82~\x04\xea\x97/\x19\xa1N\xf2c]U2a\xd7\xbe\x83\xa0\x82\xa2w\x11&RV\xa4/\x94$]\xeb.\xd9j{$\x96\xe8\xd9\x82\x81\"\xd8\xf3\xc9\xce\x89\xdc\x00=5\xa5}\x15t\xafc\xb0\xba;\x1c\xdb\x94\xc1\x0e\x8a9|\x05U&\x1d\xa0\xf3\x19\x89\x13\x8f\x87!\x88\xac\xd4\xe5\x99\x00Q\x80\x11'A\x12\xa3A]gJE\x9f\xc0t\xc1c\xcf\x98\xa6\x8a\xc3\xd8\x8aF\xbd\x00\xe1\x01\xaf\xca\x98*b\xb0F\xfd\xefP/&V\x00\xec\xb7\x0c\x95\xc4\xe6\x80:\xb7W\xa8\x9b\xce:\x01\xb2\x90\xaa\x9f\"\x14\x05ul\x90\xc9~b\xa0\x1c\x9f4:Q ~\xdfh\xcec\xb2(\x87\xbb\x1b\x9a\x92\r\x97X\xed\\\x0b\xe1\xec4\xbb\x9c\xe7\x89\x1dz\x94x\xfe\xa6Rx\x12\xc3\x86z\r\xf3)\xce\xf0G\x02\x1aG\xca\x87\tl\xc0\xac\xd0\x92\x1c\xf9\x87Kny\x8c&|\xf6T\xe4\xd1Sn\xd3\xf34w\xee%u|\x86\x85\xceQ\xe1\xd3\x80\xaak\xf2W\xde\xda\x1b+\x18\xb4\xd9\x86R'$\x0f\xa8\xd2\x17\xc9b\x15[\x8d\xf1kd\xc7\x08s\xda\xf3<\xc1\x1f\xe7\xd1.l\x0fmd\x00\xe9f\x94p\xda\xbeE\xb8>\xbdKa\xc7'(\xedIs\xc7\x8c\xe0\x92\xec\r\xfb)\x0c\xdbJ\x80\xf8\xca\x07RP\xe3\x94\x1c\x86;\xa6\x1d\xa4\x1cs\xc3\xd7\x92\xe4\xbb!\xde+\xce\x1e\x04\rw\xac+\x832\xaa\xbbop\xb3f~\xc1\x9b\x86\x91v6\xc9\xfd\x16\xf3tX\x99d\x04Q\xc1\xf4\xe4]n\xb9B\x14\xcc\xb9\x02Q\xd9=\xe9M\xaco30O\xacq\xb9;s\xfb\x01\x1cT\xe7;\xc2\xd2\x0b\xa3\xd97Y\xb9\xa0\xcf{\xafdw\xab_\xb7\x992\x81\xb3\xb4l\xfa)\xf9_\xf9;\x7fO\x94C\xe8\xaa\xfb\xa2MT\x8f\xdf8\x96uV4\xc1\xf35G\xcbj$U\xd6\x1f#@\x87M\xe1\x15B\t\xa7S\x1a\xa5\r\x98\xc2\xf8\xbf\xa8%@\xbevYj\x85\xa8\xf5\xe3n\xd0/L\xda\xed\x19;k\xbb\xb5{d^\xc2I\xff\t\x0e\xf6d\xcf\xc3\xcb\xa9[\x9b\x04\xe9\xba\x0flj-\x86\xd8\xc41\x9bA\xd0P\x83\n\x103\niI\x86S\xaeK\xf5\x8f\xf5\x89\xde\xc9#\x97\x98U\xb3\xa2d\xde6\x0f\xcd\x08\xd3\xb0SA)\xdf\\)]\x9f\x90\xd6\x84*\xbc\xe8AY\xb7]\x05\xe6\xc6\x8b\x96\xd8\xa1\xe8m'\xe74z\x0e\x87\xb3\x814e\xc8Aw\x07\xec\x8ah\xe5\x9b{\x0f\x8a\x8cG\xaao2\xd4A\xdfA\"VZ@\xc3^\xe3\x8b\xc8\x03\xca\x99S1g(\x08\xe9\xe7C\x8aR\x9b\xc4\x9d=YQ\x87\xd5N\xd5\xbf\x1a\x13\x84r\x03\xc7\xc9$Q\x805\xedWv+dZA\xa5m\xd3\x11*\r\x1f\x00$;\x99g\x06H\x00\x9f\x93\xfa\x16\xda\xaa\x99r\x91\xc2\x14\xfbmm\xfafn\x0c\x82|\xb6t\xb8\x83\xd7^A\xc4\xe4\xf0\xbc\x98\x17\xa9\x17\xe7,\xd7\xc9L\xfa\xa0xH\x95d\xa6\x82\xe8\xff]\x11\x11\x9c\xa8:\xe6~\x1f\xc0<\xc3\xbc\xc3\xe3\xff\xd0\xa0\x8b\x98\xde\xa8\x9d\xf2y=n\xa6xj\xc3}\x04f\xc7\x06!\xb2\\\x19M\xcd\xb2\xbaH\x84!\xb9\xc7\xea\x1a\x8fi\x7fh\x06\xf5{\x9dYg\xa0b\\<\x9c\xe0\xc4\xae`\xec\x17^\x01q:zn\x9aJ h\xae\xb8\xbe\xad#O<\xc7\x83)\xe1\x86,\xd9}\nM\x05\xd2\x86%\x1b\xfb\xfb/\xd7\xd9?\x1fD\x8c\xc0\xfa\x7f\t\x1c\x81\xc9\xa3\x93~\x1e\x8f\xe2\xddc9\x04\xb0\xb8\xe5\xee\x1f\x88\xedaq\x86D\x9b7\xc4\xdc\x99x\x9c+?8N$w\xc8\xa7\x17\x0e\x00\xef3\xe1\x8f\xfb\xedp\xca\x82!\x92H\x08PE\x17Ot\x13\x0c\x01\"(\xd2\x1b\xbff=\xd6\xf0P\xed\xed\x83\xec.\xda\xb4d\x02\xb3v\xf6k\xef\xa3\xfc\x14\x82\x16\r\xb5\xe8quE\x0bE\x16\xedq\xca\x97\xbf\xbd^\x92\xe1j\xbc\xf5\xf0\xfc\t\xf8\xa6\x9a;a\x18\x10\x04\x07R\xa3G:qQ?Ee\xf5+\xd6\x7f\xec\xe9\x1e1\xb5[\xe3h\xd1\xdcY~\x8cj\x12\xb3\xb9\"\rj\xeaX|\xbe\x9ej\xb9'\xc5\x9c\xfcE\x9e\xfd\xe7E\x95\xab\xff\x87\xc5\xb6\xe4J\xfe\xe3s\x04\xc5B\xce,\x01H\xeb\x04\x03\xc3\xe1\x1a\xa4*\xcdnq\x99\x87\xbb\xf5\x92\xdbf\x94~z\xdc\x14]h\xd2\x91\xb1\x8b`w\xb4o\xd4\xc2tv\xfc\x0b\xde\xe1\x81D\xcf\xc9J\x91G\xb7\x07X\x0e\x12\x1c\xde>K\xb9!\xc1\xeb\x9a\x8fF\xec~\xdc\rF\x9e\x10\xe7;J3\xcc\xdb\x97\xfe\x03\x8e\xdf\xb7\xa4Ax2G\xd7\x8d\x08\"\xf6\xea\x03\x8c.(=^9\xdf\x12\x95\x10ME\x97\x0e\xda\xe7I\xdbcw,\x81\x16\n\xcdW\xe9\xee0\x01M\xb3\xe0\x8d\xc2O\xc2\xd7\xee1f\xbf'y\x1b\xf3*\xb68\x01s\x1a6:\x0b\x80-\x12\xbc\xc8_\xc6\xfc\xbfe\r\x08n\x81\xd2w0\x0b/\x94\xef\xb6\x02\xf9\xc1\x04\x19\x05\\h\xb7x0U\xff\xc7\x9e]k\x9a\x9f\xe4\x17\x18)S\x13\x89\x80\xfc\xb4\xb6V\xd2\x1f\xe8D\xcb\xd4\xec\x08\xcb5PA\x05\xf8rwb\xdd3\xe7\x19N\x9f\x8fw\xe4\xfdK\x97\xc6e\xb5D~\t\xc4\xfa\x07\x0e\xfd\xa9S\xbd\x91\xf1r\xedB\x86\xf1\x96\xb4\xff9\xa8|\x14H*\xf6W\xd8\x9dO\xb3\xdf\xf8\x8f\xab\x0c`Z\x9a\xcf\x81 \x06\xff\x9f\x8c\x9c\x11wCb\x8a\xbe\x89\xcd[wv}q\xc5Ah\x8e\xb4>\x01\xb6\x0b\x0e\x84\xa8\xc4\xdf\x9a\xa8\xfd\x99\xba\x80p\x9a\xc2\x8f\xabk\xebq\xc1\x96\xbc\x972\xb8\xf7\xed\x80\xd5xfF\xec#\xe528\x14\x97\x08\x95e\xb2~=\xb1\xe6j\x83<\xe9\x9b\xf0\x12\xcd\xe8B\x8e\x96z\xca\xafQ\"4\x99\xdc\xa8^\xfe;\x89e\xdd\xd6\xb4G\x17\xea\x1a\xa3\xbf%bb\xca\xa3\x05.r: \x10Z\xdf\xd4g\xb3g\xe6\xb2\x96Nw\xed_Z\x16\xa5]X\xa3w\x14f\xe1\n\x9d:\x0c\xf82\r\xbep\xa8py\x97U\xc6\n\xe8D\x89Q?\xc5\xe2\xca}\xfc'\xc9\xf5\xf1\xbc\x9b\x94\xb3^P\xbd\xc5.'\xc6\xc5\x11\r\x86(\xee\x95>|\xfbY8r\x89o{\xe4\t\xb9C$`\xaf8\x7f\x16E\x16\xac,\xa2\xabue\x86h\xcapa\x0b`\xad\xb6\xcf\xd83\xa4\xb6\x11\x9c\x8f\xd7&\xd9\\Y\xfdo\x1a\xed\xf3\x02\xca\x9c`E\xe3\xc8\x16c\xd0\x13\xbc\xe6\x9c8\xed@\x89)\xefA\xfa\xee\xc3\x9ej\xe9\xb2\x05\xc0\xaah1_\x0c\x03\x1f~\xb9/T\xb6\xc0hM\xe4S`\xc48[y\xee%2\xa9\xd0\xf8\x1fs|\xba\\\xd5\xad\xf4/\r\xb2\xd2\xdc\xf0_?\x83\xd9\xc6\xa3w\xb7\xfa5\xf1'\x1a\x8e\x1c\x92\xd9\x12\xf7H\r\x11\xb0{\x01\xc9g\xee\"]\x1c\xadBr,\x8cS}\xcb\xf6o 8\x82Ca\x80\xa8:}\xce\xa6\xf4\xd3\xea\xa4\xdf.\x16Y\xd3\xe8\xb5\xee\xe5{}N\xb3\xb4d\x8amq\x8a\xa4\x9f\x15\xc8/l\xe2\t\x96\xc5\xe8*\xba\xbe\x1f\x1f\xd1\xab+7\x01(\x9e\x9b%\x05wX\xff\xe1y\xd2\x8e\xf0\x9aB\x02\xfcz\x00~\t\x11|\xb6\x8e\x94\xb9=\xdc\xf8\x83\xa5C\x14\xcd\xac\xad\x83\xe5\x9b*\x0f\n\x8b\xc4\xfc\x14\xefW-\x0e\xecVs\xae\xe0\x86\x83\xd1B\xbe\x02XN;xC3V\x1a\x10\xea\xbaVM\t*\x00\x92\xa7\xb5~BB\xf2\xb4\xd3U\x93p\xbfd\x16%\x9c05\x84fN\xdb\xf9\x1b5e\xa0&\xad\xbcsNuY:l\xd3ib\xb7D\x83@\x1c\x9dK\x9b\xf0q\xf2o\xb4[\x97o\xddUy\x9f\x93\x03\xff\xb9\xec\xd8Q\x8e\x11Q]\xdb\xe3zz\x89\xcb\xca]Z\xd3\x01\x02\t\xc1o\xfc\xa9\xbd\x1a\xf9\x8a\x85(9\xbf\x8e\xdd\xb8\x9cm\xb6\xda\x95\xe4\xcb\xbdel\x7ft^G\xa8|\xfe\x9f\x90`\x9c\xad\x87W\xdc7\xdb\x887\x11w{\xb2\xae\xbbtt\x06\x81\xb4\xec2\xbcz\x8a D\x16\x0eO0Q\xc0\xd9\x84\x8a.\xe5Q\x9d\x8e&\x9fa\\A\xfb@\x86\xf7:\x82\xbd\xf4\x13Z\xeb\x86:QJ]?D\xa9\xa8g\xb4\xc1\t\x87;14\xb6\xe2'i?I\x1eHs\x94Z\xe1\x19\x7f\xb2\xf5\x90\x9eK\xe9\x1e\xed\xd7\xe3\xe6\x0c$R\x88\xfaB\xc8\x92\xde\x05@\xda\x96\x92G\x87lE(\xaf'\x9e\xae\xfaR\x1e\x0bC\x9eH\xf7\xdf\xe3\x9f\xe0\xf9T_t\x8bB\xcahh\x81\t\x98\x82\xa1j\x17R\x1f\xf1fTl\xec\x91A\xf1t\x1aR\xb7\x7f\xb3\xbcBZ5\xb8\x1co\x9eN\x1d.g\xee\xf7$\x85\x87f\x90).\x10\xb6\xf7q\xf9\x94zP\xb7\xdb\x9b\xd39\x1d\xc0\xd6\xfe\xff\x07x\x1c\xfb\xaf%\xbd\xbc\xc6\xba\"\xf6|\x10\xd75\xc3+\x18\x1a\xfb\xb4\x11\xed\\\x8fh\xd9\xc0\t\xa1\x17\xccZ|Z\xb1\xb8\x8e\xc9#\xf9\xd6\x8b\xbf\xdfn\\\x96\r\xa0=0\xbc\xe8\x84\x0b\xef\xeeR\xfe\x1f\xf7@\x02\xbbR\xe9\xbb\xcb>\x8fS^\x0f\x92\x7f*\xf7+\xcd\xca\xdc\xc8p\x06)\xc1 \xcdz\xab\xcb8B~\xaf{}\x19\xc6\xeb\x8b\xdd{j\xe0\x01\xe4l.\x19\xd3T*\x8d\xc7H\x07k\x8b\xfd\x8eg\xcd\x89\xaa\x8a\xe6\xfb/E-X\x8a\x89\x02\xa2\xcd\x13\xacN>\xbc4a\x18W\x02\x95\x9e\xa4z\xff\x05\xf5\xa9\xb0,`*\x11}\x1cz)1\xf1\xe0\xb8\xc64\xc8\x032\xcc%z\x80\xb1\xec\x7f<\xc4\xfentJ\xd1\x10\x90\xab\n\x96E\xe2\xa2\x00L\x1dO\xe2\xaet\"B\x0e\xf4\x8d\x8c\xb7\x8fA\xbe<\xcb/z\xd6\xae\x02(\xb8\x9dL\x85?\xe7T\xba\xd7\x961\x8d\r~\xa0\x9e\xe0\x12\xd1-\x8dc\xb8\x06\xc4\xa1\xfe\x1d\x8f\x03\x86\x9a\xeeh\x1c\xdb\xb8\x96\xfcc\xfa\xd4\x13\xfaX\xa4#N\xd2\x0c\xfe4\xbdB\xb1v\xa6>\xbdE\x9c~\x1f\xc3\x17u1C_\xa5\x84d\xe8\x9f0\x9f\x98A!\x16+Go\xe6s\x95EA\x8av\x1c\x1d\x83\xabZh\xef\xe2zS,.\x1d\x91\xfe)\x19l\xfeyAR\xc3\xa1>\xe6\xb1\xef\x9d\xaau\x1f\xf3\x86Y\xf6%L%\x932T\xf3\xbc\xcckX\xf4\xebGa\xffV\x92M\xd0C\xd4Kn\xee`\x98\x84;{P(\x9be\x01;\xd6\x16#88\x0c\xcd\x97\xd7\x14\xdf\x0c\xa0\xedDc\x82W\xe6j\xa6\xbbH\xa5\x9d\xcb\t@\x0b\x10\xfd)\x9ai:\xd4\xe1\xbcU\xfdLs\x9d!\"2iRI\xe5\x93\xa1'\x86\xd8\x90\xbe\x96\xc5\x04ul\x15\x95`\x8b\x17\xeb\xef3U\xf5[\xbcV\xe5\xbf\xfc\tq}\xb9@\xb9+\x80\xb2\x02&\x7f\xc7^#\xa3\x8c2\x862\x19\x12\x97\xbd\x06\x86i\xbck)N\x05\xe7A\x13\x9d\xf0?\xd0\xe0\x10\xe7Y\xd0\x83\xf5\x1e(\xaf\xaf6\x04\xb6\xe5\xb0E\xa0\xa6\xe1\xa7\xcc\xd1\xbe\x89\x9f\xf1 b\xee\xecp\xa8\x08\xdf\xdb}1\x93\x97\x984yG\xe1\xf3\xb8\x14\"4\x1cfL,\x953\x88O\xb4\xfcv\xa2\xae\x9e\x10\xc8\x91\xa7\xc7\xcb\xff<\x90\xc0ojKK\xf2\x16\xfc\xf6rm=p8SJK\x1b+oey\xedp\x8e\x81\xa9\x9c\xaf\x12x\xc3\x8c>L\xd1\x82\xe2\xbb\xc8\x16\xc5\xf4\x0eQ\x9f\xd6\xf8\xf55wu\xc9\xf8\x0e\x0f\xf183\xa2Mc-\xc5\x80Rpu\xcbJb\x84\xb1\x1f\xc2\xb9\xc1\x07\x96\x9f\xe5n[N\xc8\xafW\xfb}2qM\xe2\xc9\x8b\x19\xe0\xc2\xc6\xc5\xc4@\x88\xf7\xca\x88\x9b\x0cC\xd0*\xeb\x16\xeb\xef/\xb3P\x96\x1e\xf3\x8e\xc9\xbf\x975`%\\\x04\x15\x91\x89TV`\xc1O\xea\x89E=7\xfc\x9a.\x98\x8c\xe7\xd0\x86\xf5+\xd7\xc0[g\x0e\xab\xe1\xed\x07\x10Q\xbe\xfc\x93 \xd7;5\x93?\x85\xa41Y-\xd23I\xf9\xf8\xb2\xc7\x7fX\xe7x'\x87fF\xbbp\xeb\xda\x0f\x94t^\x84\x8bz\xeb\x1b\xaf\xba\xb9A\x95\xd8\\\xca\x91\xea\xc3I\x97\xd4\x86\x8d\xffM\x9b\xde\x82AA\x9f\xab\x17_\x9d\xd8f\x87\xc3\x93(U\xd8\x8a\xfc\xf7%\xd1\"\x0c\xcb\xc8\xa2\xbe\xe3\x0b\x11\xd0\t^\tHf\x15\xac\xa7\xd6\x0ekDq\x036O'\xf6\x86\xfdS[{u\xdf\x97\xc7\x96\x9b-\x88\x9f\x86\xece\x8c\x83\x8fi\x9c\x8dw\x04\x13\r\x1fP\xea\xa6\n\x94\xc3\xf3\xcfvw\xe0\xa5R\xcaf^\xf5u\xceU\x85\xd0\xb3]\x85\xe8y\x8di\xcc\xd2.j\xc7\x97G\x1f\xd8>L\x18\xd1\xba\x04y\xd6\x83R{y\xc4aqB\x0c\xc8Rm\xb7=\xf6\x0e\xc4\xa8\x98Y\xe5\xd6\xa04\xf7c\xc9a\xd5\x07\xca\x11\x80\xcex\xcbb\x97#2\xec\xf3\xca\x03\xf7\x95\xcb\xc9\xd3=\x8ed\xdf(\xd2Y\x16^TiJ\xa5\xa0\xaa\xb9\xb3q\x90\x9f@\xb0\xb0\xe1\xc4l\xa3`C\xcd\xe5\x864\x064/\xd0%\xd4\xce\\\xfa\xd0P\r:\xb6x\"\xa8lsK\x06\xcb\xc2x\x83\xb7[\xf4.d\"\xf6\x02Q\xf8X\xf1\xf8g\x1cc\x03 R\x1b\xa7\x15\xbc\x97\xb6\x0f\x7f\xd0\xf7\xcb\xea\xfc:s\x1ay\xdf\x19\xdd\x12;\x02T\x8a\xf3\xa2\x84q\x04\x9bi\xaf\xc9\xe9*\xf3\x98\xe1#\xa1\xf9\xe8\xb0\nl\x8c\x12\xee\xc1\xcfH\xa3\xb3'K\xf4Ot\x19\xacY\xd0?=\x90\x0bV}\xf3+\xc8;l\xb2\x00\x14\xde\x04\x7f\x15\xed\x1eP\xc1-@\x84\x17\x7f\r\x95\xf59\xf3K\xbb\xb8\xa8Y\xe7\xc6\x976\xb0g\x04\xfc\xbe\x15\x9a\x9d\xb6\xa2yfW\xb1Y\xab?\x8f\x9c\xe3\x94\x07\xa8xP\xe5\xbe\xb8\xa3\xe9\xf9c\x88\xda\xb1\xc4\xbd@\xab\xdfe\xb0R\x99\x85y\x808\xdf<\x99\x1c\xd8\xc5\x00\"\xc3\xfd\x92\xf5\xd9\x91\n\xdd.a\x11\x9a6\xe3\x15=hyB\x96\xad\xbe\xf6\x84\"\xf2\xa0 \xa1Ux.\xb2\xc3\xba\xcc\x14x\xf0mK|\x1c\xd9\xd5m\xba\xe8\xb3C\x1di\xd3\x8f91\xaf\xd5\x8e\\\x0c\x19BM\x13c7\xc7\xed\x1c\xf7{JBy\xb6i8q\xcdT~^\xce{\xef\x91$\x85\x883\xc2v\xf1\xb0\xf5vS\xa7\xe0\n\xc5>MTc\x9d\x7f\x01!\x14\xf3x.\xee\xbd\x10#o\x18\xba\xdc\xf9\xf1\xdd\xc0.\xf3\xe3p\xb5`\xd7\x97\xe79\xc1\x8bP\xf4\xce\xc2\x1c\xfa\xc1\xa94\x7f\x1e]Q\x7f\xfa\xdf>\xa7 S'\x8e\xe8.\x8b\xc6y\xa1?\x1c;\xac'\xd00\x0cP@\xe4R>\x06\x15\xb5\xb4\xce\xe8\xdc~\xd4\x8bI4\xf6+\xe5\x82\x1f\xed\x04\xa7\xb8\x9a\xa9\x8a\\\x18\xc6z\x08\xc9\"\x97SE(\xa4KH7<\x8c\x06\xad\xb6\xe45\xf1\x0c{\xff\xad\x81\xe8\xf9\xb6\xe7\xc5\x90\xda\xb9\xea\x05\n\xd5\xd2\x0b9\xcb\xc9\xce\x89\xe0AT\x1c\x0b\xb9]\xb0\x07\xcd\xddWe)B\xb39\x9f\x9a\x0b\xce\xb4<\xa2\xef=\xd0\xc5\xfb3\xf6B\x9d\xd6\xb1\xf68\xff\x16\xd19\xc63\x81M\x89\xf0\xf67\x9a>(gzO\xcdt\xc7\x91\xe3\xbd\x81\xcc)\xa7\x14\xba[\x99\xcc\x92\xbb\xfa\xce\xa1\xd0n\xaa\x91b\xad\x1cb\xfb\xc3j\xda\x9f\xf4\xcf0\xb7@\x8e\xf5{\x14\xedU\xbc\x1d^\xeb\xe8v\xb5R\xc7T\xadR\x04iP\xf5\x7f\x9c\x0e\xf9(w\xd1\xa39`K\xea\xff\xe5\xb4\x7f\x90D\x0e\xf8\xc7\xeb\xc5q\xe8\xa5=\x94\xf9p\xca\xa0\xcf\x01\xeb\x8f8\x87\x00y\xfcm\xdd\xcff\xb8N\xde\x02Lv\x94\xeb^$\xc8Q3\x90g\xf1nMmC\xe31\x81\xb5\x10\xcb\x16\xab>\xef\xf3l\xe5\xc7\xc4>x\x88\xb8\xb36\x1be\xa41q1}^\xf1i\xa4\xde\xff\x10\xc1\xaaJ=\xa0w\xdb\x07R\xd9N\xed\x87\xb5\x04\xa8\xf2we\xf9\xca\xbc\x14\xf5\xb3\x14\xef\xf8\xc9\xcc}\xcc1;\xba\x95\x9d\xe5\xc2[#\x86\xbbJ\xa1\xa0Z\x04\xd11\x00\xe8\xbe\xade\xb6\xa3\xfaaG\x98\xa5Ad\x81#q9\x03d\x9fr9\xdf\x12y\x1fP\x8d\xa5\xd3XYA\xd4\x8c4cA\x8d\xa1\xc7]?6\x176\xa0\xc40\x1c\xd0/\x9an\x97\x1fUW\xac\xb6\xc5T\xbf\x15K\xac\xedoz\xd1e\x83tc\x99\x8f\x93\x108{\x0e[\x82M\xa1\x04\xd4\x1b\x8b'\xf9\x14\xf1\x13\xa4\x16\x83\xc9B\x9f\xaf7\x9b\x04\x9b\x15I>\xd2I<$$|\x823v\xec\x0c\xdd:%\x88e\x1f\x9ap\xa9\x97\xf79\x14\xbe=6t\x99\xc4>@}w=dn\xd5_\x90\xa3C\x91\xc5'\xd1\x8f\xaf\xbb\x05\xc5\xe8\xa2\x80\xf03d~\x0c8\xa9\nm!I\xadvX\x0f#\xdd\x0b!\x0eq\xbe5tP\xfc.\x16\xe8D\x94A4\x87\xa4\x17Y\xee&\x1f\xaae\x1d\xd3MCAG\x1dg\x82|}\x8e\t.\xdeuO\xd1B/\xe3~\xc5\x88\xa6\x156'\x07\xe2\x06\xb7\x07.\xfb\x8f\x1d\"3ju\"7\x13R?\xa3f\x16\xf4\xdb\x0c\xbe\x8b6\x8b\x8a\xaf\xd2\xa6\x9dm\x8fUg\xbb\xb3M%\xff\xcaG\xb2w\xf2\xec\x03\xb9^?\x98Xeiyh\xe0\xe1\xb0|\r\x1ax\x1a\xd4s\x03\x7f8\xfa\xc7qKk\xb8\xb5`v\x1e\x81\x10\xbe\x81\xff\xa9,\x95X_r\xd5\n\xe5\xd4\x98k\x03\xd9R\x9f2|\n\x85\x82!&R\xa51om\x97\xce_\xd64\xfe|\x92\xc0\xb4\x95e;@\xd1)\xdb\xf0n9h\xb8$*N\xe7\xcc\x05\xe1@\x136vs\x1a\xab_\xaed\xf6\xae?S\x1c\x9f5\xdb\x03\x04\x1c\x11\x8b\x97\xa3\x12-\xff\xdao\xd5\xa8!=>|h\\BT]\xd9\x93\x7fK\xfa\x07\x9ch\x9aa\x9bX\xa2X\xd6\xb7)D\xfcs\xc5P\x94\xfc\x05\xb2\x05\x04\x96\xcc\xaf\xeb\xe4\xd2g\\\xbf\x0e,\xfe\x012.{\x00[\n\x93\x00\xd2r\x96ZO\xe3-\xbc\xdc\xe3\xcc\xf7P\n\x19\xd4!x\x0b5\xa9\xe2h\xc7\xce\xb8\xa2\xb3%\xd6<\xd0\x94\x98\xabh\xd1w\r\\x!o\xa1n\x91\x12\xacT\xc3\xa9&Y\\!\xcb\r|t\xe1W\x92E>\xce\xc2\x95\xf0\xcc\x1c\x02\xbbR\xf5z`\x13\x1bh\xbc\xe0?\xd5D\xd3\x1a\x94\x01^N\xaa\x87\xa0\xd2\x19\xa8\xbc\x94c\x93+\xc2\x90\x01\xde4\xb5.\x1a\x05\x91\x18\xab\xb8\xf1\x06$i\xf3\xe41\xca\xf4\xa58\xac\xe9D\xd5\xea\x19\x7f\xf0\xcb/Q\xceWl\xc8k\xbe$\xc2'\x0b\x7f&\xfa\xe5\xc8\xa4\xd6\x0f\x19U9\\\xcb\xa8\x15\x0b\x89\x8cD\xd0\x13\xbe\xbd\xfe9\xf7\xea\x08\xc1\x17\xa3\x91\x97\xaf\xdbN\xfa\x0c\xabV\xdb\x19\x05\xc7\x8ei\xd5\xbe\x83\xb1'\xdf\x96\x03\xa5_\x9e\x0f\x0b\xf1\r\xec\xfb\x0cp\xa3\xfd|\xf8Lb\x80\x98B\xc2\x98\xf3\x91sx\xbe\xcc\xb9\xc1&+\x98Z/\x07\xa1Y\xfd\xedy\t\x9c\x91\x8d\x12\xe7\xf2;\xa3Z,\x99<\xce<\x17\xcfG#\x16\xf1\x9f\x81y \x18u\xea~\xed\x9594\x8e7\xcc\xf0\xb6\xf2#mA\xb0~\x1d&\x00\xa1\xaa\x99P\x80\x1aSs\x01\xfe'Kbr\xebts\xb0\xe7\x08\x93CWW\xbeA5\x9e\xd5B0\xf2\x863aV\xea6\x827\x95\x03\xd9\xb0Di$u\x82b\x98\xf1\xd5\xe1\"[iTVf\tFo36\xb2K\xd0\xb3\x8b\xd0\xe0\xb7~\xb9\xe2\xd9\xf3r\x18\xdf\xe8\x1f\xcaP\xf7:Z\x1d\xdd\xac\xd5\xf4\xbc<\xba\xce\xfd\xf5\x106Z\xd0\x12n\xab\xdc\xce\xc4\xbcz\xf1\x7f\x90X\x8e\x9b=\xae!Y\xcf\xc6\x87\x94\xdd\x91\xae\xdcD\x06\x0f:\x95+y+\xa7\xff\x01\xdc\xb6?'\xcf0\x17\xe6\xa1$NA*\x9cU\xe9sr\xbb\x98O^\x10\x94\x84\x8b\x11\x10\xad\xf7\x89\xd6c`\xd3uX\xb8\xdd\xc7\x86\xb4\x8d\xb7\xed\x1b\xbad\xb1i\x05\xfdt\xa6I\x8b\xbf\x9cw\xf4\xcc\xec\x92\x92\x18?7\x9f!\xfdHk\x90-\xa5\xbd\xdb\xe9\x11\xb6Pp\xe2\r\x16\xc6\xd1\x89\xf6y\xa0|\xd5\xcc\xf9\x99gq\xf3\xb1\xdc\x88kf`f\x8d[\xa8Wx\x8d\xe1\x07\xfdR\xeb>RF(\xd56\x16\xc8\xc4\x9b\x1a/uM\xefe[\x9d\x1b/9\x90\x8cY\xa6\xe1\x04K\xe0:\xd8\xa2r\xde\xc4\x9b\xad\xac\xe6\x9d(\x17\x81\x8f\xc9\x11\xf6.\xb5r\x82\x9f\x83\x827\xc8\xc0\xa0\x9ae8\xb4\xadz\x1d\xe4\x92\xd2\xdb6\xe4,e&\x98\x7f\xa5\x9c\x02\xdd\xb2\xad?\x95iq\x87\xcf+\x10\xfczT\xcb\x90xA\x13Q\x9ar\xa4\x0c{\x02\xb3p\xc25\xf0~\x16\xa4a\xaf\xb91\xd2\x94X\x1a\xbdX\xc4J\xec\x0b.o[\x8a\xd8\x0f`\x97%&\xd8\xd5\xda\xb3\xd0h\x14\xa6\xc9L\xb3\x84w\xe3\xec\xcfV,\x02\x04,,\xbc)\xec\x9d\x9bs\x1cn\x8d\xdb\x8f\x84o\x19\xb53)\xf6\xf2\x97\xb2\xee\xa4\xb6\xb6a\xdf\xa3\xaa\x83\x9f_6q\xec~\x87\xaa1 \xd8\xc5\xe1 {\xfdv4^K\x17\xe1\xb5dg\xa4\xf2\xe9K[\x80)\r\x07\xb9G%\xb7\xcb\xa3\xba[\xbf\xbe\xdfV\xb0\xd7>4\"\xc1\x11ph`[\x1a\xa2\x10\xa0\xb6z\x0e\xbb\xda\xc8\x8e'\xe6\x9f\xa7|\xdc\x1c:1s9\xf8l\xaa`\xecx('\r[ \x1f\xf0\xd7\xa7\xd7\xa1^\x84\xfa\x0cz\xfd^\xae\x8d,\xffub7\x84\xc4\x86\xa3\xea\xc2\x01\xef%\xb5\x84\xadrl\xdd\xdd\x88o ?T&|e\xcf\xbfbI5\x0e\xdcR\x06\x07\x04}\x9c\xb6t\xdcf\xd2\xee\xdfZb\xd7Y\xc0u \xdf\x7f\\\x02\x03@\x18\x01K\x9d\xa6A\xe5!\xb7\x14~\x10\xd1{\xe6,\xbe\xd3\x87u\xd5\xe1/\x07\x197\x01@\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0foCs\x1e\x13}0=\xfa0[\x81h|\xf9\xeaR\xa9\xe3\xf4(\x8c\x018\xaf\xe9\xd0\xa8,\xd4b\xe8A\xa5\xb1q\xc1.+y\xe3\xff\xa8$\x12\xaf\x89\xa7\x9ams\xe6\xcd\xe8\x11u\xff\xe6p\x8a\x8a\xe5O\x08\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f2\x91\x88\xc4\x01\x19\x08/H\x84\xd20_V\xb7\x15\xaf\x90R\x1a\x1b\x16\xcd\x84\xean\xe6\x9a\x89\xc3H\xf0\x9c\xbd\xc3\x95\x18\xf90\xc0\xd2P!fA\xa1\x82\xb6\xa5Wdj\x96\x96\x8c\x1d\x94t\xd6/w\x12K?\xf6\\3\x8c\xa1!\x7f<[\x9d\xcb,\x1fn\xa0\xaa\x8f\xea\t\x90KG\xd0\'\xa7\x9a\x89x\x9e \xf2\x8e\x81\x12\xdd\t\xdf\r\x7fKv\xb5\x89\xa7i\x7fB\x15"\x7f\xe9Y\xa6\xfdY*\x8eX%\xcc\xfcc\x88\xc5d"qH.\xc9\xc8\xe3\xae\xb4\x94\xbdsz\x11\x047\x0c\xf0\x04\x1dWboe\xfeW\x97\xbaD\x81\xa7\x9d\xb4\xfc\x16>\xb5\x05\xed\xd1g\xd5*\xe7\xcf\xd5\xd5\xd4\xc8J\x1f\x859y\xdf\xb7\x1eyu\xc3\xb3\xb4\xca\xa1=8T\xc6B\x17;W\x02\xb9\xdc\xde\xc8\x1f\x88\n\x9b\xb7N\x95%\xce\xc8?\x02t\xfd\xb8\xa2\\\x12\x1d\xd6%7\xe3\xd3l*\x9d\x8f\x93&\xe3?\xc1\xd6\xbe\x14\x8e\xef\x08\xbcM\xb4\xde\xe9\x05\x14)\xa0:W\xebRG\xd7\xde\x1dB\x97Q\xd3\x85\r\xa7\xf0\xf7\xd30\xfcx\xc3ws\x8d\x8e\xf4\x18-3\xc6\xe9\x9f\xe3\x1e\x81\x8a\x99\xdb&6\x8d\xc1\x9d\xc0\x03\xf2\xb7\xbc\xa3\xbd"\xa8\xaf]7\x1a>\x1d\x9cH\xd6\xa8\r!\xa6z\xc0\x117\xb3\x97]PZ\xe8\xdc\xc6\x7f\xf8\x165\xed(\xefQ\xee\x05COb\x15\xbe\x8b\x88\x0fl\xb0WiW\xb1\xffvDdl\xa3\x12\x9cT\\{\xa2\xc3\xad&`\xde\xf0]#\xa3(\xf5\xab\x88\x8ba\x85\x02\xc8\xb3\x1dA\xd20\x0b",\xea\xd3\xc9\xeb?#\x80\xda\xc3\x84\x0fl\xd4\xcc\x1e_m"\xact\x1d\xd2\t:\x1b(\x08\xb6\xed\x92\xe6\xa5\xad\x9b\x84\t@\xa2\x91l\x1a\x90r\x8eTc\x16\xa6\xdd\xfc\xf3#>\x11\xf0\n2,{\x81`\xffa\xf7Jz\x07\x10{\xebh\x90V\xd9j=\xdb"1e\xa2-\xa4\xb4\x82\xc3\xea|\xf8$\x88\x80J/\xa9VU\xbd.\x88\xf7&6\x1d\x18e\xf9\xb7\xb3c\xb2\xe6\x0fvZ\xf4:\n\xb7l\x11\x1f\x00\xcc1\x16\\oQ,\xc4\xd9\xee\xf6\xc4\xf9-\x81n\xf1\xcd\x13DwCg\xbd\xb6\x14\x91\xd92\xb2\xff\x96F&\xc4b\x1el\xb4:\xc5\xbc\xb8\xea@{r\x7f\xf8\x82\xdcgG\xf28f\xc6s\xd5\xa9\x8fH\xe5\x10T{C\xfd\xee\x9b\x1c\x12U\x15 \xf8#\x0f\x95\x85\xcb_\xf5\x1bWO%\x0b\xca\xa1jm\xf2i\xd8\x8e@\xecd`\x93C:\x01w\xbcKrs#\xf5\xd1\x0cp\x1bq\xe3\x95\xf9Q}\xab@F\xb3\xec8*\xfb\x9c\xb9\xa2i\xe4"\xbd\xb1k\x08\xa9\xe0\xe7fH\xf1\xb0-kS\x8bbT\xd4\xe8H\xda\xfb\xe0\x8c\x0b\x8a\x9d\xa4F\x88[G\xe5*\xf6\x84\xb3\xae1\xf6\xc5?\x11Y@|ft\x8d\xa3\x1a\x13~\xd6\x90\xcd\xc8\x97\xaf3\xba\xad\xf6\xdedA\xd3\xae\x08\x00\xf6/s\xd3!dN\xc5\'\xfa\xb6b\x02\xb97\xd2"\x9d\xe6\x9f\x08G\xfb\x05\x1e\xb8,\xe4\xc5\x92\x91\xaaP\xa3\xe4x\x80\xc5\xb0\x14O\x90\x11M\x80\xeb %\xfcs|\xd2\xd5\xf9}\x83\xa6,\x1b\x0bv\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f-r1I\xd9\x9f\xeb2r\xdc\xe0Y\xf8\xe2\xaa\xbb\x94H\xe3e\x89+\xb6\xa4\xca89\x82\x92\x1d\xed\x9e\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f\xe3\xab\xe2\x85P\x08\xd1\xa8\'\x88-\x92e]0\xbf\xa1ai\xa12\xac\xc0hUZ\x82\x98,,\x02d\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f\xad\xf6\\~\xc3{\x8a\\\xc3\xf6@(\x0fN0\x0f\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f\xff\x1dP\x0e\xfeg\xf3D\x9c\xdf\xee\xc2J\xfb\xca\x04\x96\x16\x10\xf10\x17N\x7fL\xf8\x86S|s\x15\n\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f\xf4\xad#UB\x96\xed\xc0qu\x9b\x1cp\x17\x07%\n\x83B\xeb\x81\xabK\x1b\xe59\xa0\x9e\x98\xd73g>\xf0\xfa\xbb\xb7\xbdq\xd1M\x11R\xc3+\x9c\xdaC\xa3H\xeb\'\x04\x0en\r\xf6B\xa5\xb7\xb3\xc5xE\xd8(\xceR"\xc5\x82\x0f\x1f\xa9\x0f\xce\xd9\xd2\x1f\xa5\x8a\xfe\x93\xbc\x02\x18/|\'\\g\xc1\xe0\xf6\xbd\x94\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0fS\xf1\x82\xf9\xdfY\xf3<\xa8\xaf\x18h\xff\xd8\x1b\x19\x19\xcfB\xeb\xe2\xc5k"\x90J4\xe36\x8aI\xe1\xeay\xfa\x1fy\x8a<\xe3\xc4\x8cFIV{\x80\x8f\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f\xf9\x85l\xc3n\x9a=\x9c=\xac\xd0\x9c\x11\x8f\x82\x1cE\xc6\xf3\xe6\xd6\x12j\xfc=al\xed\xbbz\x08\xb5\x13\x9dC\x91ui M\xe2\xbe\xa70\x93\xf7\xa7\xc1Zl5S\x86\x032&k\xd8\xd8\xa7\xdc\xe7\xf3B\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f\xbe\x85\x0cE\x9ep\xc6\x84\x15\xa3\xc4.`\xad\xc9\xb9\x99\x95J\xbd\xd9C\xa5V(\xe9\xcf\x96\x8a\x05@\xcf4dqi\xca\x92\x9f\x1f\x01H\xdb\xfds)A\x94\x9a\x92\xeftq\xa5\xe0\xf9}\x11\xcfkZ\x81tw\x1d%\xc1\x18\x9b\xde\xf3\x88\x18\x88+:\xd7\xd4\xdaW\xf6\xe0\xe1\xcc\xd2\x83a\xea\xdf\xbe\xc6\xee\x82)1\x03\xc3\xb7D\xd2\x8a\x00\x1eO@tVr\xcaO\xadDl \xd7\xa3\xa2\xf4\xda2Q\xce\xaa\x8d\x7f\xd1\xd1\xfb\xc0\xa3>\xb9\xb4\x8eT\xda\xe9z\xd6\xba\xfdT\xb7P-\x02\xa4\xc9\x8a\x1e\x82\xb5\x11\x8e8\xaa\xde/\x84dD\x03\xa6\xf9L\xd7j\x8f%o\xd6{\xf8Gq3(*%\x01\x1d\xea\x8c\xbabe\xe0[^\xa8o_\xee\xa9\tk\xb25\xbb\x07@\x8a\x99\xb9\xbb\xde\xeb{\x92s\xc5z^q\xa9Z:\xc1vtO\x0c7\x9a\x9cf\xdeA@\xb3\xbfX%\x88\x05\x0b;b\x06\x89\x12^,\x82~\x18\x93`\xaeqjy\x1c_\xb6p|\xef\x16>l\x9f\x88\x0fl9\xe9\xed\xcb\x01<\'\x08x\xfa`\xb5\xd4\x14\xab\x10\xb0\xe4\xa2\x8f\x80On\xb7E\xcb\x81\x84\x86\x83\xfe\x15\x8b!Y\xd7\x83*Oh[a\xc1IU\xa4\xb3\x03\xd8,\x7f/\xdd\xed\x8e\xd0\xf2\xbd\x12M\x1eSK\x1d_\x08%\x9b=\xa2\xa1\xeaD\x99mq;HI\xfd.Zq\xec\xa0\x86\x13&\x02\x0bI\xf8\x10\xd6`\xaak\x02\xdf\xe5\xaa\xba&\xfa\xcdP\xde\xe31\x93SN\x0few\xf9\xbf)\x95\x86\xb9~\x83E\xdb\xf2J\x05<-\xddXj\xea\xfeSw\x7f/\x05\xf7)<\x17i6\xb8\xdb3\x13\x8dv\xfd\xa5\xbce\xae\xfd\xc7\xedH\xc9L0@\xd68Z\xce\x1a\x04\x8f\xf8\xeeD`\xad:\x94\xa3\x8c&c[\xc1\x18\xc6s\x7f\x12 \x04\xb5gZ)\xb5\xe9\x8d(\x92\x05\xdag\xa4\x9f\xb8\xcc5\x0f+\xf1\xb9PF\xef\xa0}\xc6B\xea8N\xe8\xb4\xe2\xb1Le\x18\xd7\x18s\xd9m($m\xebM\xf7\xbd1\xac\x8c\x80\xc6\xf8r[\xae\xf0\x16\x88%\x9a\xef\xb2\xe5\x8e\xad\xd0\xc2\x8d\x96\x80\xb6\x00\xd0\x08,\x8c\xe1\r\xc3W\xc0+\xf7\xa5Z\x82\xffi\xad\x01\xe6B\xcd8MN\xb6m\xc6\xa4jS\\\x13\x92\x056\x02\xb3\x98\x8e\x9e\xbbHt\xe3.\x86\x84\xff\x80\xb4\xee\x94?\xbb7\xd7\xc3\xa8KZ\x85Zj\xb7MK\xb3GolC\xba\x128a\xa1a,{P\xfa:\x05L\x16\x0e/\x88l\xcf\xacO\xb7\xd9\x0e\xc7Ur\x9d\xf5d\xc4\xb8\x9a\x82\x18\xdaQ,\x7f9\xc1\x17\xb9\xf4/\x98;U{i\xcc\x83\xe3\xdeuD\xfdU\x06sG\xc7\xeeG\xa2;5\x17\xf0\xf3\x0b\xe8\x01\x97wg(\x14\xa4?\x96t\xa2\xa45\xe3\x1fiAZ\x89O\x19\x06\xdf\xd7W\xc0T\'r\x0f6\xe0\xf9W\xc0\x9aV\xfd\\\x19\xc5yP\x88\xb8pW\xdbU\x98\xa8/\xbb\xb8\xaf\xf8\xe53\r@\xbe\xbc<~\xc8\xff\x11|\x129v\x12\x9c\x8d\x9c\x95#j\x1a\xe9\xaf\xd7\x9b\xd1\x8e\xa12/\x17M\x84\x9c\xcc\x8f\xa9\x14\xec\x86\xcf\x1a\xfd\x1dE\x14]\x9b\x0cc:\xf2\x84D\xaaMiv\x152\xd2\xcbk\x030\x9ajdf\x8c\x06\xecp\xcc3\x92\xaaC\t\x06\xe2RH\xe1v\t\x0fD{@\x04{\xd7\xbd\x8c\xec\xbd\x8e\x16\xbf/@Hrx\xa0E\x16\x907\xaaz\xca\x8fzl\xaah\xb3\xebc\xe9\x7f\xd0\xe7:\x82\xff\xebE\x7fu\xdc\xb5\xf9j\'\x8eI9\n\xae\x98$\xc4\xee\xf5\x80\xbc\xf50O}Z\x0cy\x0f7=\x9cS\xd6\xee\x95\xea\x85T\xe6\x9a*\xcf\x80\xdc\x14v\x8d\x9c\x83\x1f@\xacf\'gi\xb6\xbc\x05~\xe9\xc6\xce\xb2\xd6\xb1\xacy \x13$\xce\xc4\xd1\x02k\x88\xd4\r\xd9A\x9d\x94q\xf2\x06\x15\xdf4\xf1M\xb3\x02\x84\xae\x83}\xdc\xc8\xc3>S\x01\\\x1d\xb0\xfe\x84\xa3s\xa9j\x8a\x13\xd3\xef\x8b\xea\x90x\x87\xb5\xff\xce4\xf9x{\xad\xb8b\xde\xb5\xb5l\xf9\xb3g.\x83\x9dR\xbeD\xd1\x89\xd6+\xe4Xg\x9d\xac\xc4%\xebP \x1f.\xf5\xe78\x05\xefp\x9c\xf3\x0cJ\xb4G\xd4\x1c\x89\x9c\xd3\tj\x97\xcc\xf3\xc6\x85J\xb3\x0f\xaf\xf0\n\xc0@\xe0"\x19\xeb\x81c>]6(c\xcdH\xbb\xb5?R\xd2\xab\'\x01\xc4ug\xf5\xc2\x89CH\xcfK\x8c\xb2\xed\x11\x87_\x16\xff\xc7\xdcwJ\xfe\xea\xee\xc4\x9d\x9f\xb4\xa2:\x01\xd3 \xeb\x95\x84\xadL\xcc\xd9\x12\xa1K\xc7\xc3`&\xba\xdb&\x9f\xf1:f\xe1\x8c\x06\xd1G\x0bw\x84\xaa\xee\x8a?\xcbQ\x8e\x15q\xb7Ey\x8c4\xc3\xb2V\xe5\xc4$\xaf\x05?V\x86\x87\xae\xa2\x96\xa4x\xb2)4\xa5\xe3\x02RZ\xd6_\x8f\xe7U\xe8\x89\xca\x1f\xdd)\x81\x80\xba\xa0\x0c(\xfa\x85\x8a\xac\xa3\x8fH\xb5\xc2\xb8\xd1\x87\x0f\x89[\xa1\x94,\xe4\x05\xc6`\x94W\xc2iS\x01\xa9\xef\xc4=\x92!\rx,\xfeXe\xbb\xb7\n9j \xc4\xaeK\xf0W\xee\nY\xa0q\xd1\xbf\xb99\xc7\x12<\xaa\xca\xfb\xce\x0fCH\xdd\xa7\xb5\r%\xf3\x88\xa7\xd4\xda\xdck\xbe\x186\t\x82\xe8\x99t\xd1\x83\xff\x94+\xa5\xd9\xc0\x8e\xbf\x0c\xf3\xaf\xce\x06K\x86M.\xb8\xaa\x0c\xa5\x0c\xc38\xa8`\x0e\xd9Xq\x10\x007\x99\x81\x9d\xb8O\xeft\xac7\xbcWSN\xaf\xae\x87x\xfb\x82\x18`x\x99\x98\x16\x01AB^\xde\xdf\xa9\xbd{\x93\xdc\xc4\xb8\x9fN\xd5\x8a \x15I\x0c\xcf\n.n\xde\xcbgY\x1b\x1b\xb8$\xb0\xb0\xe4\x13\x1a\x8eN9\xf4Ri\xe3\xdc\x95\xc0\xc8\xc0\xb3\x96\xe2r\x99\xa1\xe9\xfd\xc4\x9e\xfaC\xd3b\x17kT5}\xb1\xbf\xa9\xb3\x03\x186s\xe2\xc7\xc2\xd9\xb25k}\x9fU8\xf9\xa1a\xa0\x994\x029)!\x97\xdf\x87\xda\xcb\x87uO\xfaWTi:\x97$\xfe\xbe/\xb4{\x12\xc3\xa7\n\xe99\x9a,\x08j\x05f\x0f\xd38\xa5\xd9\xc8\x83*k\xc5D\xe3{\x01\xab2\x96\x8c#*\x14|<\xbbFQ\x04\x12\xb6\x1b\xb6\xe3\xf0\xad#\xebg\xf8\xb9\x95\xc1\x98U\xe3u\xa7\x1a|:\xb8\x9d\xa7\x12\xdf\xfc\xa0\x1a\xbb\\\xc8i\x95Zg\xe3Z\xfc\x14?\x17nT\n\x80\xa9Q\xe8A \xfdX\x121E\xd3P\xf4FguK!\x94U\xc6\xda\xed\xd5\x0f\x87\xb9\x7f3\xc3\xd1\x0b\x83c2r6\xed\xa1*\xf8n\x88B\xc4\x94\xbb\x00d\xc1r%6S\xbbq\x02hx\xc1z_p\xd0\x8d\x15\x94\xc0\x90\xa7\x81O\x870ID\xc8\x96\xed\x9cn\xd4\x9d*\x81s\xd3\x89\x8c2<\xad\xac\x0b\x99z\xd8%\x94w\xb0!$N\xe6Gl\xb1k\x87\xf9v\x95e-\x05\x03U$\x1fk\xaf\xc2k\x17\xac_\x0ct\x06\xab\xdd\x040\xc8\xd6O\xd1\xe8\xa2\xf4\xb1\xe0G\x19\x00\x13\x83\x87\xeb\xc7\xd9\xablW\xda\x00\xd4\x9dMmf\xc7Q\xb5\xcf\x1f\x91\x04\x160\xcc\xce{\xd2iw\xed\xcc\x07m\xebc+\x99\x16\x14\x1e\r\x1d\xda,\x98\x16\xdf\xdc\xd4\x92\xd3\xccj5\x80\xf1\xcc\x0f\xf1\xf7C\xe6\x82\xc6\xf5j-\x16\xcc\xfb(#\xe0\'\xb5\xc1\x83\x88\x17\xb2\x9e$\xbd\xa6\x17;\xbd\xf8\xfb\x96\xc4w\x93.QE\xb1E\x97:\x08x\xa04kK\\\xdf\xfe@\x04\x8a\xe9\xfb\xccl\xd6V(\x89\x7f\xde*\xc3\xd9\x92\x8f"\x03\x1b\xea"\xab\x99\x18[G\xc3\x06\x02\xbc\xbbB\xb4,\x05a\x97\x86\x9bw\x91[H\xach#\x01b\x7f\xa5\x7f\xf0{o\x047\x91\x13\xf4\xeb<.,\x9a\xe6\x1f\xb1_\xaf\xd4\x8a\xdbw\xcc\n\xa7|\xc4F\x02\xa5\x8f\x81\xef\x929\xb0\x8c\xea\xfaLw0!\xe8m\xa0L\ne\xfa \xd1\x7f\xcei\x11\x1fc\xfbp\xcbB\xe1\xb5\t\xb2\x02\x83g\xe8` 4zY\xc0zz\xc1\x8d\x83\x0e\x90:r\xafl\x9f\xa5\x95\x1b\x1d-\x98R\xdf\xcfU*\xad\x13\xd28\xa5f\xbci\xa0\xa37}\rpc\x17IC\xa1\r\xda\xae\xd1\x02\xfc\x0fn\x7f&\xd8L\x16\xab\xb8jd\x03i\xf42i\xcd\x17\x85\xf9\xce\xd2\xbe\xae\x9cY\xd8P\xf1\x93\x1c\x06\xc62a\xc2T\x85\x88\xf3w\xfd\xa3\x8d\x82\x94c\xb4\xcaLG\xe5\xb1\x02\xa4S\xbb\xdfC\xe7r\xd7\xe1\xd0\x18\x06\xcecc\x8a\x96\xaf\x1f\xea\xcd\x9bt!\xeaRz\xde\xba\x98\xa7\xae\x01\x9a\xd5\x94\xf7\x07oFI\xe8\x08\xeb\xa7Jm\xf0\xc6\xfd\x9ed\xfb\xdbG\n"\xb5\x93\xf3\\\xa4\xf7\xee^\x8c\xbd\x15\x06e\xda\xbe\xf5\xa1p\x18\x1b6\x914e{\xe2 \xa9\xa2K\x9e\xbc\x7f\xae\\\xceX\xc6_\x0b0s\xb6\xd4\x92\xd9\x85\xfedS\xd4\x03\xafk^FiZ\xeces\xcd\x98\xe1\x11\x9c$\xe1\xcd\x81}\x91\xf9\xd3\x86\x9e\xa78\x00\xa0\x98!\xd7J\x1d\x86\xf4N\x964\x8e\x9f%=\x95\xa3\xd8\xb7z\xfd\xb0\xa5\xc81s\xa1\x9134\x88\xaa\xfb\xb8V*\xe3\xd6\xa7\x9c\x98KK\xdcm\xc5)\xa4\xc0\xc8\x11\xcd\x1e\x19k\x9e\x82\t\x90H\xaf\xde\x08\xbd\xbd\xc0_\x9b\xb2"\x1a\xbd\xd7\x0f\x9d\x1c4\xfa\xa2\xfc\x96\xe0G\xa7\x1a\xc1)\xba=\xcc;_\x84\xcf$\'\x1c9=\xb3\x99\xd1\x061{U\xb8\x1bF5\x9bw!\xec\x8f1\x9c\x8f\xa8\x97\xe9\x08\xc3\x86\xb4\xf0\x98,\xf1\xef\x96R:\xc5\x9c\x91u\xd4_\xc1xy\x1az\xc8\x9a\x10@z\xfe\xaf(c^\xf6\x10B\xc6\xc5-y\x8c\xb2T.\xfe%\x7f\x12iG\xd9q\x97\xf5\xa9\xc8\x0c\x9a(\x1f\xde\xfb\xd9\xdcy\xd8np\xfdt \xd5\xc9Q\xcf\xc3-W\xa9\xeee\xaa\xc3\x17\xd6!\xba\xfaCS\xd2\x84\x86\x0c\xd5QHd@vG\x1d\xd5\xef$q\x85\xfc\xf7\xcb\xca\xe5>V9"PO\xaf]:\xe2\xe4\t;h\xcc\xfe\xd5\x0c\x9d\xbb\xd2\x16\xa1\xa5\x82\x8d{\xac\xefz\xe2\x88\xb6\x19\x8f$\x1eSz\x8c\xe9\xd3b\xc8\x9e\xd15`\x8e\xc3#\xabp\x838\xfc\xf4o\xff.a\xdf\x07\xa8\xa4\xbe\xd3\xd7\x97>=\xc9\xad\xe6\xcbG\t4\xc7\x1f\xd9|\xbc\xe5\xb0\xe2M\x9e*\xfa\xff@0\xe5\xfe\xffU8&\xc5\x0e\x16\xbdS\xc5$\xa7\xe0Z\x89\xaf;\x07\xa2\xf7\xcdB!\x8c\x934\xcf\xf3ez3\x1a\x8b\xe4WT\x9d\x1e\xcc8\xbe\xac\xf2YNJ\x05\x9cd\xdcn\x87J\x93\x94\xe6\x04d\xbd\xec\xa8\xc5\xca\x8a\xbe4\xf4\x0b\xc1\x199Y\xd7\xbdK\xb2\xa3\xe7\xb7\x0e\x03\xdc\x02\x03\x87]\xc1\xb7\x8f\xd9\x1d\xfe\xa1\xda\x1d\x9c\x88`\x14\xba\xcd\xa78\xfb6E\xe2\xabG\x17A,>\x89,\xa8y\xb2\x91\x17\xefcM\xe8x\xb5\xec\xfe2\xca\xcc\xe3\xd3\x7f\xd7\x93"\xd2l\xad\xd7\xc2\xf6.3\x7fJ|\x99\xe5\xabPXMK8\x00Q\xf0\x9a9~\xb6\xfe\x86\xeca"0x\xe3\x86\xe0\xe7\xa4u^\xf3\t\\\xc5^W\xe0\x08\xda:P\x10\xe3\xefc\xcf\x14E\xff\x94\xd4\x08\x0e\xd2\xa7\xe3I[\x99\xfc\\[__\xc1\x84,NB\xf5b?\xec\x01le8\x1a\xd5\xd4X\xa4\xc5\xea\xf2\xb8\xf3\xbe\xd6\xa2\'9x{\xb3\xf6I(<\x0c\xb4\x1a\x10\x14x\xd4\xb1q^\xffm\x12\x88\xea\xfe\xde\xf4\xd4\xd2\xc2Q#\xd23[\xc45\x8a\xa1n9\x8c1\x16vJ\x1b\xcb\x91D\xfdd\xbb\xa6\xcb\nV\xebU\x8d\xea\x94\x91\xf7\x9d\xe6\x9f\x13\xc1\xb8\x1e\xbc\x1e\x8e+;\x87\x9a\xd82\xf8\xc4\xadi\x08\xf9\x10\xd3\x9c\x89\x03\xa8\x96\xff-\x85\x81\xf4e/r`cT_\x97\xb6F\xb5\xb7|\xe0\x16a6/AK\x81\xfe${\xab\t4\xcd\xa0@\x0e\xb1\xb1\x05\xa2\x88\x14"\xe3\xccEb\xd24\xc5\x9f\xeb6\xf4&l\xbf\x9e\xc1r\xf8j#\xa7\x87\xcf\xd2\n\x997\xe5\rhG\xacMRG\x00S\x15hC\x12\x9f\x9b\xf8\xd9\xf9_x\xaa\xb5A\xb9\x84\n:\xc8*o\xff\x0b\xf0\xee\xb4\xe8\xe4B\xcb\xbb\xdbF1\xd0:\xaa\x13\xb9\x9d\x98\x85\xe5\x8bl\xa3\xb6\xd1\x97m\x81\x17\xf0ce\x81@%1\xcc\xefqV\x81\xa6\x81\xcaC\xbb\xdcy\xaea\x0e\x99\x14\xc2\x8f\xd8nT\xc0q\xcf\x98S\x0e\x0bd\x87n\x88\xf8\xa1\xc0\xb60X5\xec`\x04\x01\xc8s$\xb4\xb0F\xad\xc7K\xfb\xec\xc3\r\x86D2\x07\xd1\xc9\x94\xa7\xe4N\xd4\xd7\x14\xfc\x9f{\xd1=\x94V\xc2|\xedb\xfd\x91\x87\x08\xa2kD\xe5\x8c(\xad\xf7E\x15\xd3v\xaa)\'\r\xc2r\x93\xf0Z\xb8\xbe\xbb\xd4\x0e\xa7\x11\x13\xfc\xaaG\xd2M\x05\x93\x1b\xbd:\x01\x0eS13<#\x83\x8ae\x1e\x82f<\x0feg \xae:Z\xf8M\x8f\xa9|\xa0&\xbd\x1f\xe38O\xbe=\xcf\x9fPB\x95\x1cv\x1a\x9aA\x08\xd9\xba\xb9\xd6\xf6eA"\xd4\xdf\xbdN\xfdX\xd5\x1b\x07\x141\xe5\xa8\xbf\x88"\xcfp[r\x9d\xc2m\x87\x0fo\x1bl\xef\xd7\xd1\xc0\xeeH\xb4\xa2\xca\xc9{\xb8\xe8\xa2]95\x89\xfa\xebx\xceQ\xb1\xba\xe6\xa4' # noqa: E501 chest_file = self.location / chest_id @@ -121,18 +104,18 @@ def _getRawFromFile(self, chest_id) -> bytes: return xor(data, key) def parse_from_log(self, _=None) -> dict[str, QuarEntry]: - logging.info("Parsing from log in %s", self.name) + logger.info("Parsing from log in %s", self.name) if not self._initDB(): return {} quarfiles = {} # Return the value of a field 'f' - @log_fn + @log.log(lgr=logger) def get(e: ET, f) -> str: return e.find(f).text for idx, e in enumerate(self.root.findall("ChestEntry")): - logging.debug("Parsing entry, idx %s", idx) + logger.debug("Parsing entry, idx %s", idx) chest_id = get(e, "ChestId") path = get(e, "OrigFolder") + "\\" + get(e, "OrigFileName") # Check if an entry is in the vault.db @@ -155,31 +138,31 @@ def get(e: ET, f) -> str: def parse_from_fs( self, data: dict[str, QuarEntry] | None = None ) -> dict[str, QuarEntry]: - logging.info("Parsing from filesystem in %s", self.name) + logger.info("Parsing from filesystem in %s", self.name) quarfiles = {} # iterating over bigger files, which were not logged to vault.db for idx, entry in enumerate(self.location.glob("*")): - logging.debug('Parsing entry, idx %s, path "%s"', idx, entry) + logger.debug('Parsing entry, idx %s, path "%s"', idx, entry) chest_id = entry.name if not entry.is_file(): - logging.debug("Entry (idx %s) is not a file, skipping", idx) + logger.debug("Entry (idx %s) is not a file, skipping", idx) continue if chest_id == "index.xml": - logging.debug("Entry (idx %s) is index.xml itself, skipping", idx) + logger.debug("Entry (idx %s) is index.xml itself, skipping", idx) continue if chest_id in data: - logging.debug("Entry (idx %s) already found, skipping", idx) + logger.debug("Entry (idx %s) already found, skipping", idx) continue malfile = self._getRawFromFile(chest_id) entry_stat = parse(self).entry_stat(entry) if entry_stat is None: - logging.debug('Skipping entry idx %s, path "%s"', idx, entry) + logger.debug('Skipping entry idx %s, path "%s"', idx, entry) continue timestamp = DTC.get_dt_from_stat(entry_stat) size = entry_stat.st_size diff --git a/maldump/parsers/avg_parser.py b/maldump/parsers/avg_parser.py index d09dcc2..06415d6 100644 --- a/maldump/parsers/avg_parser.py +++ b/maldump/parsers/avg_parser.py @@ -5,36 +5,19 @@ import tempfile from datetime import datetime as dt from os import unlink -from xml.etree.ElementTree import Element, ParseError +from xml.etree.ElementTree import ParseError import defusedxml.ElementTree as ET from maldump.constants import ThreatMetadata from maldump.structures import Parser, QuarEntry from maldump.utils import DatetimeConverter as DTC +from maldump.utils import Logger as log from maldump.utils import Parser as parse from maldump.utils import Reader as read from maldump.utils import xor - -def log_fn(func): - def wrapper(*args, **kwargs): - logging.debug( - "Calling function: %s, arguments: %s, keyword arguments: %s", - func.__name__, - tuple( - ( - arg - if type(arg) not in {bytes, AVGParser, Element} - else "<" + type(arg).__name__ + ">" - ) - for arg in args - ), - kwargs, - ) - return func(*args, **kwargs) - - return wrapper +logger = logging.getLogger(__name__) class AVGParser(Parser): @@ -43,48 +26,48 @@ def __init__(self): self.tmpfile = None # Cleanup - @log_fn + @log.log(lgr=logger) def __del__(self): if hasattr(self, "db"): self.db.close() unlink(self.tmpfile) - @log_fn + @log.log(lgr=logger) def _initDB(self) -> bool: # Parse index.xml try: - logging.debug( + logger.debug( 'Trying to parse index.xml file "%s"', self.location / "index.xml" ) self.root = ET.parse(self.location / "index.xml").getroot() except ParseError as e: - logging.exception("Cannot open and parse index.xml", exc_info=e) + logger.exception("Cannot open and parse index.xml", exc_info=e) return False # Decrypt vault.db and prepare db connection self.tmpfile = tempfile.mkdtemp() + "/decrypted.db" try: - logging.debug('Trying to open temporary database file "%s"', self.tmpfile) + logger.debug('Trying to open temporary database file "%s"', self.tmpfile) with open(self.tmpfile, "wb") as f: f.write(self._decryptVault("$AV_AVG/$VAULT/vault.db")) except OSError as e: - logging.exception("Cannot open nor write temporary file", exc_info=e) + logger.exception("Cannot open nor write temporary file", exc_info=e) return False try: - logging.debug( + logger.debug( 'Trying to connect to SQLite3 chest database "%s"', self.tmpfile ) self.db = sqlite3.connect(self.tmpfile) except sqlite3.Error as e: - logging.exception("Cannot connect to SQLite3 chest database", exc_info=e) - print("AVG DB Error: " + str(e)) + logger.exception("Cannot connect to SQLite3 chest database", exc_info=e) + print("Avast DB Error: " + str(e)) return False return True - @log_fn + @log.log(lgr=logger) def _decryptVault(self, vault): key = b"\x92\xaa\xbc\x89\xef_\x1b\t\xaa\xad5\xf8\xadg\xe9+^Z\xfe\xdd\nt\xf8\xfb\xc3\xa5\x1e\xad\x87\x00\x9e\x16\x82\xec\xdb9(;w\x10\x16\x17\t\xdd\xef\x898\x8c\xff\xbbV\xf7\xa4\x01JU\xd7\xd6\xe2b\xda\x14*\x9c\x8a\x88\xe1\x8a\xb1\x8c5E\xbaZ\xa1\xae}6\x02ac\xa3\xf2`\xaa8\xf1~vv\x07\x1a\xd4\xc2I\xd4(e$\x98\xcf|\xf2\xbd\xc9\x92\x88\xce\x82\xdc\xc9q(i\x9e A\xb8\xea\xf7,\xb9\x9cRbm6\x96fY'\x90\n\xf9\xb5\x9a\x94\xcf\x9e\x96R\xb0\xeb\xdd&f\t\xe0\xe9Ls4\xc5Q\xb6\x1e\xdeHS\x01\xff\x89\xb2]\x93\x08J\xe0\x06\"e\x96\xefg\x8d\x89>\x86^\xd5\xcf\x03(\x08\x9c\xa0(\x8a\xd2\x07k\xc1\x81\xe9\x1a\xd9\xe5\xf3$g<\xf2nR\x13,,G\x07]K\x8dGOKn\xb2\x93\x13ZHR2\x08\x8cu\xac&t\xb3\x08\xba\xfci\xde\xcf\xeb?\xd9\xa0\x97c\xaa\xf8,)\x8b\xe9w\x854o\xa0\xa2U\xb1\x16F\xe6\x13\xda\xa9@\x87\xe0m\xdb\xdb\xef\xb2\x8cy\xa4\xfadX\xddH\xec\x97\x91\xf5\x05\xc5\xa4\xf4&63\xd6\xe8\xa1\x12\xd5\xe7\xb5%\x15k\x16\x05%\x0eZ\x17\x9e\xe2\xb1\"\x1e\"\xc0\x02\xa4\xfb\x1b%{-TI\x8a#\xd2\xdcO\xd5]\x9c\xa3j22\xb8\x01\n\x1f%m~o\xa3TW\xbb\xe8\x14?\xdf\xc2[\x81^\xd4\t\xd4\xb8\xb5\x9dX.\xd4\xf2\x18v\x13E\x88\xacU\xf2\x91\xa9\x0e'\xf2\xee_\xd1\xdb\x95\xbb\x8b\xb5b\x1d\xcb\xef\xf0\n\x01r\xb8D\x82\x84\x18S\x12\rL|\\Vz\x9c\"G4Y\xee\xa4g\xff\x1e\xec\xb2]\"\x04H\x07.P\x83\xd1\xd4\xbfZ\xb6\x0fa\xf28\xe4\xdc\xed\x18\x82\xdf\xae\x90\xef\xfd\xb3>T*\xcf\xf0\xb4{\xbf_8Bg#I\x1f&\xfe*]5\xcf\x1f\xbd\xee\xca6\x80#u\xae\xc6\xb3\xfbp\xb3\x9e\x80\xec\xb2\x8eB0\xb0\x13?\xab\x0e\xad\x0b\x91{\x16\xfd\xa4p\x92~NYK(\x1e\xb9WlW\x1e\x8d\x0c\xa1\xc9d\xd0\xb84\x13\x95\xd0acjP\x96Jf0\x15 \x17\xe1\x08\x06\x0e\x1f\xa0k\x89 \xfe,\xc2\xf1\x14\xfb\xbe:s&\x82E\x15\x80\xb7t\xa3R+\xb2'\x06\x89\xffZ\x80\x14\x98\xff\xe5\xac{\xc3^\xb3\x8d\xa5\x14\xf0\x08s\xd1!w{\x08\tl]\xe4\xc3Ys\xaan+\x1d\x19\xa9\x86M\xd5\xca\x87\xb5\xb4\x13\xf2\x06\x15\xfdKy\xba\x03 \xe1\t]\x0eyS\xc6o*[\xf5\x92JE\x0c\xc6\xa4\xd8\xa3\xb2@\xe1\x05\xf2\xd2\x9d\x9a7\x98wC\x93\x053\xae\xc4mL\xb3e\xe2\xb0\x9f\xcdE9O\xd3x+\xd4h\x9a\x159\x1ak1\xf4\xb5\xddc\xda\xb8~N\x0801P.\xb3D4C\x84<,\x99&\xf48n\xe5\xb7\xb4\x9fP\x10\x02\xb7\xc6P%v\x19\xb6\xa1\xe1\"\xfc]\xfap\x81\xa1\xa8\xc8\\\xc5\x00\x03\xc6)K\xae\xac\xd0\x15\xff\"cj\xc2vTW\x99U\x97\x7f\x88\xa2\xbd3\x87)\x84\xa2\x07M+a\xe5x\xcb\xcb\x13w\x15\xf7\xbeRe\xbe\x9eVg\xd2\xf6\xd2\t\xbb\xc7\xed\x98xW\xb0\x87Z\xf8\xf84\xe8\x87\x10\xcfv\x89;\x8c \xddJrJ\xd1u\xdd\x85S\x8b\x96\xc1\x03\x97]=E\x01\xbc\x93\xa4*\xfe8\n\n\x1d\xc9S\xee\xdcm\xdc3\xe2\xaf\xcc\xb0\xa2\xea[\x1a\x0e>\x1e5SEkM\xee\xca6\x10<\x18\xf0\xbaZ\xa3sy\xdf\xcf\x13D\xac\xbc_-\x0bc}\x87\x8cZ\x8b\x83\x8cw\xc8@%\xb1\x84u\x1d\xcb\x8eE\xe8\x82\x92*\x1e^\xf0\x99N\xce~,e\xf9v\xfc\xa7\x8c{Oc\x08c\x1aFH\xbe@\nr\x7f.\xe6\xfb\n\xfb@\xd7\"\x92\x15]\x00\x8aV\xdb\x01\xa6)3\xee\xcb\xf3O\x91\x9c\x1a\xe3\xbcD\xcdTG\xd0\xfe4\xf0XbX\xfa\x18\x1e\xe8\x01c\xff\xa2~)\xa1\x1cJ\x80T\xbd!x#\xba>w\x07>\x95\x92q\xa4\xd4\xab\xad\x8e\x1c\x87t>\x10\x03\xb1?H\x08\xafx7\x07|H\xfd\xa8\xf6y%\xe6Mp\xe1tIC\xaeJ\xb6\x14\xed\x1b[\xa5\x9b@\x04\xc7zu\xb0\x11\xb6\xaf\x1e\x0f)\x96\x00\xd9\xe5\x8c\x95{\xb5\x11\x02\xf3\xe0m\xc4U\xfc\xc5\x11\xb4\x89\xb4\"\xff\xbb'\xb8a\xf8\xaf\xbf\xea8\xebvG\x1d\x10qq\n\xdd\x9d\xdc\xf51\x0c\x91\x0e\xc0d\x0eUf\x88\x12;\x1fY\x89Kf\xc9\x9c\xbe'YuM\x18v\t;C:4z\xcb;\xeb\x01j\xda\xf8\xa2d\x18\\Y\x92\x0c\x86@\x1a,\xe3\x1e\x14\x96y\x08\x95\xe6RmP\xffT\xb8\x12\xd1\x82f\x80\xfd\xdb!\xd8nky\xe5\xdb^y\xa6`\xea\xe8\xbe\xcc\x91\xab\xb8\rVG\xa7d\xef6k\xb0L\xa2\xe8\xc4^F!\xfc\xcbc\x00X\x01\xcd\xf5*:\x1a#ck\xba\x9b\xdb4\xc9`@\x00;\xdaJ\x15WM\xa9\xec\xa9\xaa\x97\xea\xb0\x044\xb7\xc4*}\xc4y\xfa\xe4\x86\xbe\x83_\xac\xf5>B/s\xa5\xea\x8a?!KhY?\xb2\x18]j\x02+\x93V\xe5\xe9\x9b\x92\xf1-\xcaL\x94\x87\x12\xd3\x9e;\xb3\xa0\xc1 \xb9\n\xa9\x00\xf0\xd0\xc9\xa2\x8fj\x04\xa5\x02R\xf3\xb3\xbd\xe2E\xc5F+\x89'\x1c\x81\xd9&4\xd0Fn\xa6\x16\xa8\xc0\x99a\x15\xb8\xd9\xe5\xf6\x91\xe6\xfcb\xef\xac\xcc\xf3\xf1\xef\xa3\x04\xcc\x867\xc3\x8d\x1c\xc5h\xb8\xf94\x81\x07\xe3B\x0c\xdd\x82L<\x97\xa5\x92\xd3\x0b\x8b\xff\xa2]m\xaa\xc1\x1f\x94o\xf7{\xbaI]\x8a\xf57B\x85M#\x9c\xb1w+\xbd\x95\"\xd9\xe8I%\xe5\x19!\xdbY\xf2\xd6\xf6\xcap\x10\xa9\x1e|*\x96\x7f\x87\x18 Vs\x99g\x19\\\x08(\xc9\xa7\xa7\xafj{d\xcb\x9ap\x87\x13\xa7\xd3\r\xf0Z\x11\x8c\x8e\xf0\x94\x9d\x9c\xcb\x89u\xe7M\xed%\xa12\\\x1b\xaa\xccO\x0f\xaek\xc9\xfb\x0fP\xe4\x02\xd4 d\xf2\xa6\xec\xf2\xb3\x10\x91\xad\x91\x88\xdaaW_E\x10\xb3\x9b\xbc\xd2U\x849\xdc\xb5K\"\xe0\x12\x90u\x9b\xf0o\x9d\xef)1\xf7-V%(\x05\xc3\xfc>\xe9\x8e\xb0\xf4r\xf9\x1b)>5\xd6l\xaa\xa3\x8dg\x14N\x89a\xfbW<\x9bw'\xac|$P<\x8a\xf6\xdf\xce\x97\x816L\xb6+\x83\x80\x01\x07\x98C<\xc5\xefo\x8fi\xd02\xe2fb\x9e\x08\xdb\xaa\xbd\x9ba'&\x81:2\xc4\xe8\xbe\x1c\xc2\x02\xd8\xc4\xf8\xd16d\x82\x00\x1e\x03l\xf1)\x90\xda\x8c\xe9\x93\x91\xc1\xb8\xf7\xd6\xf5*\xc3\xf5#\x93W\x9d\xf1\x97\xa7\x87\x06k\xbf\xa4j\xe7a\x13iW\xd6\x9b\xbf!:\x1e\xfc\xd7:\x92\xba\x05\xc6\xa2L\xfd\xcfv\xce\xd2\xbe\x99\xc9,\xf2\x02\xa2hB\xa1\x14\xa1\xd7N\xa7\x90\xd4~\xac\x83_uz\xb0C\x9ff\x00[;2Hj\x0f\x96\x16\xe6I\xca~\xa5\x1e\xeas\x9bz\xe7!QMZZ\xfc\x01n\xdfl\xd3\x06\xf4z\x08\x0b\xe0\xd9Y\x02\xef\x98\x89\xa8\xcc\xbe\x17\xab\x08\x89Z7{\xa0nY6\x93\xa1\x12f\x8ac\xb1\xb0'\xac\xa2o\xdf\xf9}\xe4\xf8\xae\xda\xf2\xdb0*q\xd8\x87\xd2`\\U\x9bj\xd3\xcb\xec\nG\xb2U\xe0q\xe2\x85\xbc\xaa\xe4f\x0b\xaf\x00\xb7\xac\xc1}ez\xb5\x95B\x91\xdbT@\xd5K\xca\xc293\xa2\xceB\"\xa3\x83\xf9\xebn\x8f\x936\xfc\r}\xac\x00\xac{4\x1b\xceyN\xf3\xa7s\x06~\x12\x0e\x12l\xd3?\xd5\xb4\xc5aw\"[ \xa3\xc4\xc9J\xd0i\xf6\x0fe\xef\xdb\xe2\x9c\xd6%2%?Zq\x0c\xe3\xa3F\x0b(\xc8\xd1\x92\x9b\x1a\x06\xc9z\x12o\xde\x075\xd4\x1e4\xfe\xe3\xf7\t\xf5\xabtPu\x8bxwF\xbba\x8aX\xd0w\x82\xfa\nT?\x03@\x16\xc3>\xdf>\x82\xc9\xdc\x1a\xcf\x7f\xa3\x14\x83N\x95z\x1a\x1e\x1a\xd5f0\xc8\xf2z\xad1?[?Jj\xc8&q7X\x10\xc7w#R\x87\x81\xb2k\xcb\x19LNrq\xc7I7\xfb\xb0\x818\x14x.\xa6\xdcZ!\xe4\x8a\xad\xa7 \x81\xec\x0e\x85\xca\x86\xdd\xe9D\xc6\x1b&M\xeeW{[X\x87\x1d\t\xdcK \xd7\xfd\xceN9\xf5x\x17&\xd1\xa9\xe3q65\x84\x03\xbe\xc8\x19\x91\x9e\xbb(r\xe3h\xe1\xad\xb8\r\xf2\x8d\n\xe7t\xb9y\xf5\xf5\x1fq\x95\x97,\xe6\xe4\xbciQ\xdc\xab\xe2\x87)mh\xb3\xf7)\x82\xb5\xd9\x0c\xfeE\xff\x8f\xdc\x96\xb4\xca\xf1o\\\x19-\xd3\xbfa\x8b\x87\xaf\xd3\x05\xd18\\j\xa5\xd1\x87G\xd4\xe5\xc9\xd8)u\xf0o\x86\xfaQ\xad\x94\xcfK%\x1a:\"o\xcd<\x89b\x16\xd5\xf8\xd6r\xb2\xcdHO\x04[~\x14\xbf\xaa\xf1\xb4T\x8cu\x13\xf9\xf5\xd5\xec7\xa9*\xec\xc2v%\xbb\x98\x96\xb3\xc3f\xeee1\xd1\x7f?\xc0YwD\x04yn&\x92\x01\xd7M\nE\x88'\x08t\xd6\xde\xdeF\xcc\xf0pS\x153}Ut3 \x80\xb6m\xe8\x89\xdf\xcb\xb9h\xe268\x0f\xfb!~\xbaE}>o\xf6p>\xc3\xd5\xf7\xee\xa8\n\xf2\x8c\x81=P\x0f\x1a\xd5\x17\xd9\x16\x19\xb7\xfbi%(\x11\xd1t\xf2/\x90\x91PR$\xd7k,\xb2HE\x1c\x0ek\xe4\xa4\xe6\xc9\x8a\xb0Y\xa3\xa7\x1d=\x01\xe5\x00\xb6n\xa6\xd7A}9(D\xbd\xb5TJ.\x9d\xa2\xac\xc0\x91\xd1\x0bQ-,\x89\x15m,g\xde\x0e\xd9\x11Pa\xc5\xfc\xb7\tRY\xe5\x94\xc1\x01/\xe4\x92x\x1f\xfa%s\xd3\r\xb5\xb2O\x97x\xb0\xb6(\xa5R\x1a\xa7\xa2\xd4\xcd\x99\xfe\x05l\x7fh\xfa\xc7\xcc)\xfc\x1ee\xbe\xf7\xcc\xdb\xc2\xddg\xe1\x9cUL\xd7\xb4\x8e[+.\x03(\x19\xc8\xb6\xfd\xec:\xab6?^H\x04\xbdc\xb2\xa4O\x0bo\xc0(\x19%h\xc1\x87\xf2X\xa2\x05|>\x1fh\xcd\xa0\xd0_\x9f\x88\xfd\xbf\xb8\xd2I\xf1\xaf\xf4\x0c\xb2\x96\x1eq\xd0ss\x11\xf8\xf0\x06\x18\x97\xb5\xb2\x92g\xe7\xe5J{n1\xedUo\xb1\xd9C\xa1/\x8b\xe8R+\x167?\xf5\n\xdd\xac\xf2&\xd7\x07\xf6Nd\xe8U\xea\xecq\x7f\x85\x1a\xbd\xed@\x7fL\xfc\xe8\x9c\x18+\xb8X\xf1\x7f\xee[\x88x\x91\xcd\t\x15N\x16\x98?9\xdf\xd06\xb3\xee\x99\xaf\xddw\x00*\xbd\xd9\xaeQ\x04\xd8S\xd2\xbb\x0e\xa5\xf7\x06%w\xd9\x191\xe2\\\xdb%\x8f\xf7\x9b\xe0\x98\xf5\x1fx0-\x9d\xcb\x8f\xfe\xe0p\xfc\xed\xf1\xa4\x98\xacr|3\x82\xf0\xf8\xfd\x94\xb6\x8a\x14\xe5\xf2\x06\xaf\xee\x9e?\xcc\x10\xbf\xe0\x83\xcb\xdc\x7f\xcf\xc5\x13\xe2\x9e(G\x8a\xae\x84\xf9sJ_ \xbf\r5\xde6\xbf4\xa1\np\x9eC\x8b\xb1l\xa3\xa0PFI\xc0\xac0c\x9f\x08\xc7\x8b^\x1e/9\x95\xda\x8a\x8f \xe1 T2{^\x8e\xa0\xee\x0fc\x88\x82\x82\xafM\xc6\x05%I\xbf\xedb\xaeD\xf8\xfc}\xbb\xd2npd\xd8q\xde\xd6\x06\xf4Q\x80g\x8b6\x92\x8d4\x06'E\"\xa0b\xbc\xde\xc4\xa3#\x9eu\xdeR\x9b\x9aR\xc2\xcb\x04t\xd3\xf9pu\xe8\xb1f\xd4\x8f\x91\xdd\x9e\t\xab\xaa\x10E\xd6\xb4\xec\xfe\xca1\xcfnw.\xcbR\x80\x817\x12\x075X\xdf\xd5h\xc5Q\x1b\xcei\xc4-e\x16D\xfb\xfb]\x06\x7flz\xd8k\xdf\xb0\xd2\x910\x83\tr\xbaa\xee0\xe8V\x84\x03\xf7\x91H\xd5\x82\x9b5Q\xdbM\xb1\xaf\x07\xf0h\xba:\xbf\xd0zAr\xc8u\xaf\ta\x85\x83\xfc=\xa0\xb4\x99\xd0}0NxS\x16:\x15)\x1a\x80\xfc\xf5vf\xc8|\xff4\x8ekw2A.N\xfa\xd6\xd6\x1d\x93\xfc\x7f]'\xb2G\x84pBX\t4\x1e\xbdI\x84\xc5\x8a\t\x1e'W\xd7\xdc\xb2\xb3\x9aJ\x11\x83\xb9\xf1\t(]Z\xc2\xf0N\n\xb4\xeag\xefY+\xcc\x08\xa5\x07\xd3Z3?:\x9d\x96@\x7f\x9d\xc3p<_AD$\xbb\x8d\x1a\xc6=u\xab\xe6\xde\xc2\r\xf0@\r\x1d`?\xc1;\x98\xce\xef~z&\xc2r\xdeg\xaeH \x82\x91s\xfd\xdba\xd9\x1a\xad@\xc9\x01l\xd9w\x81\xb5\xd2\xe3\xc7:\xf1;\xbf4w;\x15\xf4\xe5\x9d\x0f\xe9\x94y\xaa\xa5\x04\x91m\xaf*&\xfd\xea\xe23k\xdd\xc4O%\x18)&~\xd9\xd2\x91\xd3\xc3\xb6\xd7S\xc1\x12\xdfm\x08\x8c\xcb8<\xe27\xfae\xb5B\xbbz\x8aL\xa7\xde2\x89\xc8^\x05\t\x92\x91\x0bp\x14R9Go\xa9v\x05q\xa5\xf8\xb4\"\xa0\xe8S\xfa\xba\xce\x87\xe1q\xccu\xf4S?\xdd\xc7\xc6v\x8d\xbc\x7f`\x04\xbc2\xd9C>8%.\xfb\x951\x17\xdf\xeb\x04![+W2V\xa8\x07]\x8c\xff0\x15O\xe2!AA<\xa5\x87\x06\xbe'p\x8ch\x05HA\x11u\x990\xcf\x96\x8c\xa2\xa3\x9a\x7f\x8a\x08\x0b9\xe2\x19-.\xc83?\xa7\xba\xe5\xc3\xeb\x7f.\x04=\r(FO\x08\xa0\xeae\xc6\xbbCMsP'&Iq\xf9(\xaf\x00\xa1+\x17N\xd1\xad\x0fV9Lp\xdc\x81\xc4\x04\xd1\xc7^1~\xf1\xcb\n\x95\x9bb\x1c\xcdj\xcdm2R\xdb\xe7\xf2\xfeB>9\xd6$\xb7\xeb\\\xbd\xa6\xd4\x0e\x04\xce\xb9\xad\xeeiqz\x8d\xcb\xceJ\xeb9o\xb8\xfa\xd6w\x82\xb2\xdd\\\x13\xdd3\x14`h\xd4\xfe\x1c\x9c\xded\xff\xfe\xc4^\x99]\x10\xfbq\xe6\xd6\xcf\x19gq\x80\x93\x84Ms\xa0\x1c$\xd1l\x8b(\x04\xbf\xcf\xf3\x8b\x08tV\xeb\xa9\xfe\xaeMDh\x1d\x9a\x84\xca*\xb1o\xb7\x81A\x9aj\x96\xf9\xfa6\xfak\x8b\x97\xdb\x1e\x8f\x94\xd7\x1a\x7f\xb7O\x1c\x97E@\nT}I\xdb\xbc\x95}j\t\xe0\xd3\xb9\x03x\x87g+\xb0\xf9P]\x01\x19\xd9\x95\xe6\x877\xd5\xcb`\x81\x12\xfc4\xd3\x9c\x08\xbf\xbd\xff\x18\xb0\xf5\xadG\xe4\x94\xd6\xde\xa2\xd3R\xd7-t\\#\xf8s\x14\xbd\xe6s\x12\xcfk\x0c\xfcq\xbb0\xbc\xf5S\xd2\x95R\x08$\xc6\x97w\x08\xee\x00{\xfdd]\x13UV\xe2\xce\x9a,2\xdb=\x04\x9bg\"\x9b\xea*\x8d\x03\xfdT\x1c\xc8\x8aI\x80\x12\xbc\xa6O\x93\x93\xf5\xaa\xfe\xa8\xd0\x8c\x13\xbfy\xba\xacw]\xaf\xd2\x07\xdc\x97\x86II\x9a\xc1\x08A\t\xaa\x0f\t\xd1\x04+\x8a\xe5\n.\x90\xc2\xc2\xdc\xe7\x9b\xb6\xe3\x1e'\xadc\xe0\xfdx\xec\xee\n\n\xb6\xf2\xdeEC\x18\x95\xe9\xfe\xff\xc0\x1d\xbaG\xdf}&_\x96V%W\xccY\x169o\x9a\xca\x0b\xa3\xf1\x19\x05\x8e\x1b\xbd\x90T\xb8\xc7\x13_3\x1dx;\xcd\xe2\xcd\xc4\xeb\x00/;j B\tf[*\xa2\xc3\xb7M\xa7rs\xd3\x8fc\xa2\xfa%\x05\xe2\xc7\xc4e\x07PoM\xbe\xd4\xa1\xf8G\x98(\xa6\x8b\xcc\xb4i\xbdm=\xdb\xb1\r;\x10bf\x1c\xd9o\x97\xd9\xd1\x01\xa0 #a\x17\xa2\xb4x:p\xf71\x93\x12\r}\x98e\xecq\xb2\x81\xf1o+z\x0f\x9f\xe0\x17\xcf\x940\x84S\x87\xc9\xa0\x05~v\xa92\x18y\xfa\xc7\xea\xc8A%<)\xa8Qo\xc4\xfc\x14\x96\xa2\x85Oq\x86;\x05\xf6\x8f\xab\x16\xf8Dy.@ \xa7\xfah\x1a\t\x02\x82\x01\xdeF\xdb\xac\x19\x0e\xf1\x982:\x883\xf9\xf4\xcb\xe5u\x0f\xa61.\x81\x11\n\x96\x97QK\xfa\x80\rGg\xf8\x80\xdd%\xf0\xb7\x84\x83\x1c\xe8\xf5\xe9\x87\x82aO\x80\xb1?\x9cMu\r\x02\xe17\xa6>p\xe5\x01!\xe9MXi\xa0R\xd9^\x90b\xacm\xc3\x07\xc0]G\xf6\xb3\xfc\x98A\xf3j#x\xd1Z0\xfe8(\xcc(}\xdep\xe4\xbb\x83\r\xd2\xb2\xb4\x0899H\xbc\xbc\xc5g\xb8\x03\xac\xfd\xd3\x07\x15\xf6\x15\xda \x16\\k\r9\xdf\xfe\xac\xf6h\xee\x01$\x89\xca\xb6\xefXpP`c`\xe9@\x94\x80\x10\x1a\xc3\x0f\x94Z\xdd\xff\x8b\xef\xebP\x1dj\x8aE\x7f\xcc4\xf1AbW\x92\x9d\x83Z\xd6\x80\xf7T\x85\n.\xe4\x0b\xd8\x8c\xae\xa4\xdd\x11P\xd2\x93w\x87\xdc\xa4\x00q\x02\xbfiD\xab\"\x80\xd0\xef\xb6\xd70\x1e\x00\xd5\x95\xb4f\x9d\xe4\x10\xfd\xf7o\xe4\x9aGU(\xf6~+\xd6\x17\xb0\x0ejF\x88n2\xd1\xdf5T\xc5.\xd0\xc6\xa5\xd5\xbb\xf3e\x86R\xe1\x8bX\xb7\xd3q\x13\xf3\xbb\xebM\xd2\xa0Y\x1dfG\xf0\xd5\\\xa1b\xcc'W$\xad\xa8>0\n\x07\xa8!Rk\xd5\xdd\x1d\xd0\xf4\xcf\x98\xa1r>}\x95UP/|f\xc7p\x0c\xd4\x17VAWf\x13`\x9e1\xa3\xadA\xb0\x8f)\xf8\x1c\x04\xfbQ\x95\x8c9_y\xe5\xe5\xc7\x06\xa7}R\xf9\xbbO\xe9}X\xeb\x98t\x8b\x19\x94\r\xdd\x1a\xbc\xfb\x01\x9bc\x96\xfe\xbc\x85 \xba\x11\xc8Gw\xae\xfb(\x0fs6\xe0zb=\xedo\x02\x84'S\x8c\x96\xdbH\xa1}\xe3h\xb8z\x08\xbb\xef\x1b\x98\xe8\xafY\x8b\xcb]\xa4\x14\xb8\xef\x90\x0b\xd9-\xadA\x04\x99P\xc3s\xc1\r6\xf3\xb5\xff\xf57z\x94\x1b&\xc07n\x83\x82\xe1\xa5\xe9\x8a-\xfb\xc92}\xba<\x83\x97\x05\x9d\x08\xcb\xe5\x12fdM7\x96Gm\xaaT\x9e\x0b\x80\xff6q\x0fAf\x10w\"9\xac\x81z\xac\x98\x19\xfb\x07sX\xaa\xf3\x08n\x11\xd6\xdc\x1c\xe6\tM@\xb4\xf7\x90%\xdbb\xfd\xe0>\xa1\x03\xd3\x0cx\xfd\xc6\xa4\x9b\":\x83K\xca\x03\xb0\xbe\xd8\x12\xdf}\xe2\xca\xc7\xc8;r\xd7[\x07m\xdfd\xb2\xdb\xd8\xc9\x81\x90\xa7\xe1\xf2\xcd\x1aSZ\xd7ULR\x95\xa1@qrq\x89\xab \xb5\xdd\xfa\x9bG\xd2A\x98\xef\xf8Y\x0b)B,\x01\x9e\xff\xf5 \xb0\xd3\xd0&\xa3\xe7S.\xbb\xbbf|\x80\xbc\xbbG\x1e\x97e.\xaa<\xda\xd5G\xc8h'\xfc\xc0\x9d\x95\x7f\x9b+\x91dVZ\x08\xc9|\x83)\xcf\xc3!\xf6\x93\xff\xbe\x92\xa0\x18\xb4\xec\x10X\xbf\x97N6'<\x8d4\xd5\x7fLZ\xe7I3N\x18\x14bH\x9c\x07](q\x0e<\xe12pg\x85\x17_\xef\xa74\xdf\x8bY\xbe\xbe\xaae\xb3>1\x99J\x9e\x1b\xe6\x05\xba\xfbWzp;\x02XhY\xd4\xd6\x7f\x87[\x0b\xa7=\x83\xacG*=\x90\xc6\x9cZC\x15sH\xf7+\\\xbe\x05_\xde1\x01\x10\x99\x95-\xcbr\xed\x95\xb9`\x7f\xae\xc1\xe3\x0c\xb3|\xb6\x88\xa3P\x96\xa5\xc5\xf5\x89KPs\xac,\x86K\xfb\xa1\x987\xce\xe0\xa0M^\xe4\xae\x9eG65=<\xc9.\x1e,\xe3\xaal9q\x1f\xae\xa6\x1d\xdc{\x90\xb6\xb1\x03\xe7\xa4\x9c\xb7\xa7y\xf1\xe7\xc2\xc1s\x91P Q\x901\xe8\xda\xbe\xb0\xe1g\x9b\xdf\x1bC\xed=\xbaL9\xc7\xf5b\xa6u\x14\xceli\xda\xf4mx\xe78U\x8fF\xe3\xafa\xe9\x00\x1a\xf5q\x15z\x94\x1d|M\x0b\xdfx\x04\xa5\xb0\x80\x0c\xd3+\x97\xaa\xdc\xf5\x9co\xd1\xe7o\xa3\xeaC\xefZG\x93\xa1P\xbc|\xf4%\x8b\x80\xb0t|\xd2\x80X\xae\x8e\xf8]\xc5\xc1\x86{\x06\xe8\x98\xa5\x1d\xf5D\xfb>\r\x0c\x0e\x17\rME\x05\xa1\x87Xg\xdfP\\\xae[\x18\xf5&~$\xee\xb6\x19\x9f\x98|n\xce\xba\xcc\xcd\x06\x88\xfd\xd8O\x9a\xf5\xb3d\"\x13\xa5\"9\x0f\xab{\xc8xw\x11;\x90d=w\xe3\xb1\xd2\xa1\xeb\\'QX\x1b?\xa0=\xb4\xe6$\x17N\x8b\xc1\xd9A\xa8\x92\x97\xe6\x92@\xf3\x07\xfc\xbeT\x97\xecku\xcdV\x90\xf31\xdc\xaf\xc7\xf7\x8e\x81}`\xeew\x93\x7f~M\x80\x91\xf2@\x07\xe3u\x97\xdavF{\x7f\x15\x89\xa6\x00\xca\xd4\xb0\x0e,5\xb9\xd3\xbb\x8bZ\xc8\xba\xc1\xddP+bF\xbe/K8\xc7\xad_\x84\xd5a?\xdadR\xe6.\xdb\x15#\x8b\x9d\xaa\xce\x15\xa7q/\x04\xab\x00\x9dj\x16\xdc\x81f\xae\xf7s\x06\x84,P\xcf\x98Z\x94i\xdb\r\xfb\xc8\xc2T\xe7\x19\xbd\x1a\xc3\xdb\xb1\xd6`KJ\xc4g\xd3\xf4\xa9\x1a\\NW\xc6\xcb*!;\x9e)\x8ej\x1c\xb8u\xb9d\x80\x8bjg\x9a\xec\x18\xa2\xc5>]+,f\xc3\x16\xee\xc8dr\xec*\xcdE\xfe\xd9e;:\xc6\xefN\xc5`\x83\xb7\xb1Y\xea\xa3v\xd5Ng<\xd1\xa6g\xee\xe5V\xe9\x9f\x80\x16\xc8\\\xf7\x04\xe3\xf0\xda\x07\xabe`\x1a\x94\x8c]\x89r8\xf4\xcb\x9a\x0b\x0e(\x9a\xd8e`7s\xaa;8Bbkz\xc2\xe2\xe7\x9d\x95\xdd;A\xda\xd1\n\xd4\xe7\x9a\x01\xcb\xfb^o\x8e\xfb>\x95%s0\xb2\xcc[`\x80\x88B\xf5\xcfT\x83K\x1c\xcf2\xaa\xac\x97\x8f?\xc8g\x0b\x16\xa1BP\xdeZ\x8e\xce\x0e\x07x\x04\xd2\x0c;\x98J\xe6\xb5+\xc8\xa0dT\x9b@\xa3\xa5\xc8\x0c\xe6:\x12\xcfg0X\xb4\xb6\xf1\xf8T\xd8\xf8\x0b9^\xd3\xb2\xe5\xd0\x8d\x93oV\xef\r\x19\x86])\xd0\xd1J\x94\x82L\xa3\xdd\t\xaca\x9b\xc9\x18\x02:?\xf1\xbf\xe78\xba?\xa6\xe3\xd0\xb3\xdeL8*\xd7\x9fSd\x18\x8b\xb9\xa8M\xa1\xdf\x17@\t\x9a@=wZ\xd9~\x9a\xa3O9\xf0\x0b\x93!\xa9+\x9a\x96\xea\x89\xc5!7\xe1\x95L~\xe01\xcdQ\x92X\xfdJM\xf9S\x13\xad\xab\xce\x9f\x1ck\xfcP{M\xa0a\xa7\xd8\x8c{\xaa\xdb\x11>\xdc\x8az(]l\xa3U\xdb\x15+\x9a+\\8\xc7\xbd0\xc1\x98\xc9O\xb0\xfb\x07i6\x98I\x1d\x1a\xe8b\x9bc)\x94x}\xd1y\x86\x94\xe6X\xd4\x1c\xa1\t\x9f\xdb\xe4Z\x16\x8e\xa2Z\xf9\x8boj\xf0\xbd\xa8e\x92\x13\xea\xb8\xf4\x99\xa9]\xf4!\xf6\xbb\x9c\xc8\x1b/\xf5zR7\xb6u\x7f\xf8\x929\xbb\xf5\x12\x02\xc6\x1e\xdbm(>\x94\xe5\x17\xd3\x9c\x03_0\x05\x16\x93S\x90_\xc2\xd5\x00s\xc8\xe1\\\x9dk\x93\xc1\x1e2,\xbc\xe4,q\xf1\xa2\x16\xf1\xac\x95\\g\xe59\x1a\x1d58\x1c\xce\x9d\xa8kp\xff\xc7\x0c\xf6j\x82h\x13V\xdd)\xee\xd9(\x01\xc7eN\xa3W\xb6\xc9\x83x\x92sM\xde}\xa0V7\xdf\xc9\xeb\x0c\xe30\xf0\xe1\xbdOUQ\xba\x1f\xd3\x03\xffr\xd3U;w\x06n\xaf\x89\xd4\x8f?\xe0\xea\xa8\xea\x03\x18\x89\x9f\xdf\xdc\x023!j\x84\xf3\x87\x8e\x01b\x9b^\xf5\xda\x94\xfe\xbba\x7f\xe0?\x17\xc1\xffb\xab\x05\x81\x99\xffH\x19\x07\x91\xfe\xc4\x7f\xf4r\xa63j\x83\xce;\xa9\x08\xb4\xd6\xd7\x99\xf7\xe3sm\xb5\xc9hmAD\t\xbd\x89@\xfd\xeb\x9b\xf4\x85\xcb\xa8\xedG\xbf\xc3o\xaa\xeb\x9cK\xf8\xf9\x08*\xad\xa2\xe7\r\xd0i\x8df\xe6\xf6\xc3n\xbf\xd0\xe9\xe0M\xb4\xf1[lf\x16gS\xa0\x9f*\xcdWI\xa8~\xd6\x10]\x8c_\xb8|\x19 \xc4\x00\x93~\xa7k\x9c&\xbf\x9a\xefhU\xdd}\x14V\xe9\x11\xed\xe2\xf3\xeb\n\x0c\x87e\xb49\xf3eh~\xbc\xe5d\x1b:\x0c\x06\xf9\xffJ`\x96\xd1\x82h\xfb\x94\xe5\x07E%\xae\xed;i\x9e\xaf3\xe4R\x8c\xef\x0f\xae?\xf9Va\xc74\x12\x8f\xea\xd5\xde\x8e\x90\xcd\xbe\x15\xf6\xf1\xa2\xf7\xda8.\xeeR\xc8\xa7\x8a\x1e\x90\xa8-\x97\xf9\x1dl\xcf\x9e\x08\xa8SQ\xab\xf2\x8e\xb8Y\xd5A\x930s\xa2\xe85\x89-\xf5\xf1\xf1\\\xcb\xa9\xe7\x8e\xffn\x9aXut_:`\xeb\xf4\xc1B%{H\xc9\xa2\r\x0f\x1f\xbc\xcad\xfbdI\x1f\x8a\xa7LZ\x98^\xda\xda\xd2\x9e\xe4L\xaeS\xa4PD\x91YT\xcem\x1d\t\"9jepP\x04\x13\xca%\x06\xb9\x96\xf3|\xa5%\x04d\x83\xb5\x87\xe2b\xa5@\x1f\xba\x07\x97\xe8>S\x8a\x82:\x8f\xbb\x0f\xb2\x86\x8a\no\x8bd\xbf{\xe4\xa2\x8e5\xc1\xd5\x8b\x9e\xd0\x87\n\xe4\xd2\xafv\xb9\xe7\xba\xfc\x17\x01\xbd\xcc\xa4Q&Fl\x1cy\x87\xb2\xc7B\x8d\xb0\n\xab\xcdC\xd6\x9d\xe9Wp*\xa8j\xbe\x82\x91\x13\xda\xb1^\xf6\xca\xb7\x14\x85\xb1\x07(AH'g2\x00\x89\xbd\xcb\xf30h\xf8\x1b\xf4\x867\xcd\xfe\x1a\x1d/!\\\x85Y\xd2\xa1\x03\x05\x17\xe6\xd1m\x99l\xb1:\xb1\xadu\x8a\xef\x91H\x81\x81\x12\x8bc\x1e\xc5\x06\x0e\xadMbY:\xf2\xc0\xb3\x1e\xe3\x1d\xd0O\xda\xb81\xccP\x11\x82\x12\xd5\x91$\x7fU\xd2m\xa8\xa0\xbd\xb3\x8f\x9dMfL\xd474\x19\x81c\x81\xb1\xab]WTt?\xc3\xfe\x7f3\x15\xbep\x02:\xaeV\x8e1\x00\x06\x12G\x1d\xa9K\xbc\x93Dm\x8b\xc5\xb9\ta()H\x11\xd0z\xf6\x10\xf8\x9c\x01]W-DM!\x121\t\x01\xdc\xf1n8\xab\x82+\x1b%\x0cG\xf9\xadAt\xfb\xc1\x05\x81`:\xfe\xc0\x17\x92f\x14\x119\x80\xff\xc3\xb2=\x8d\xa5i\x86`\xf1\x06\x81\x1b\x9b\xcau2\xf1\xe5\x82\xe4\xe3\r#u\xae4\xb0E&\xd8\xacy}\xa3\xe7\x0c\x8c\xce\xaaJ\x8d\xe4\xcf+\x04\"U\xb5\xb7\xafF\xaf\x97\x04\x94}\xfb\x88\xdb\xca\xc0\xe2\xd8\x08KU J\x0fe\x16N\x92\x06\xbbr$n\xa1\x0e\x08ed\x946\n0_\xb3;\xb3\x9d\x0c\xce\xc7\x85]\xa5\xf7b\x17\x82\x7f'\x8c{dg\xb9T]N\xc6;[\x9a~[\xcd\xc4\x02\x98+:*\xae\xa7%\xc5{\xc7\x05\xb8\xfa\xc6\xc5|\xe9\x92G\xa4\xb1\xa6G5\r\x94.\xbf=\xc9\xc3\xc8R\x0fa\xb5X*\n\xc1\x11q\xf37\xec\\\xf9_n\x7f\x08\x1e\xffV\x95y1Nx\xb9\xbaIJ\xf9\x14W1\xb4\xdb\t\x01r\x1d\xc4\x1a\xa0m\n\xb6p>/\xae\x05Z%P\x88$v\xa9+\xdd\xa8r\xf7B.\xd4\xd4\x97(\x1a\x14X\x94\r\x0f%WU(\xb4\x10\xdb\x14B.L.\x1a\xca\x184|\x9c*\xca\xa8\x82\xe3\x12:\x1c;\xa5\x83\xe4e\xebp\x12[\xcc\xf1\xb3\xd3a\xd3\xf9\xd8\x1f\x94\xd54\xdeX\xe2a\x9b\xa4tn8\r5\xaaX\x99\x0e?\xf8#l|!\xaai\x0f\x17Y\x98\x85\xc9b\xa8\x1cK\x11H\x05\xaf\x8c\x05\xab\x87pgwX\xe8\x7f\xc9\xd0jU\xd3\x1drs\xfd\x07\x95S|\xd3\xe1\xba\xf7?\x8d\"\xf6px`\x8e\x04\xea \xee\xb8\x15\x9b\x15\xa0\xb9W\x1f!\xbf@\xd6\x85|\xba\xab\xe9w\xa4\xa4\x11&\x8a\x14\xfcl\xe9\x94\x1e<\xdd\x92\xa7>\xf6+\x1a\xf4\xee\xd0\x08x\x1f\xe8s\x18j\xc7BAsi\x9bN\xc5\x87\xd5!\x8f\xe7\xd1\xedQ\x162#H \xcb?\x8a\x8d\xa2(\xbf)`\x7f\xac\xaa0S\xfb\xcf\x15j\xd7FU\xf6\xd4lT\x1b\xf3.x%\xdb\xb1\x12ttBQ\x89\xccF\xd7\xa5\x12\x05\x13\xbcM\x8d\xc3\x7fr\xe2\xfam6\x88\x8d\xaeK\xc2\xb1\xa8\x82\xd1lb$\xa7\xffB\xf8\xa3\xe8\x89:Bpe\xe6\xde\xcf\x91\xe1X\x18\x00%\xb4\xeeTs\x05\x1b\xeb\xe9\xe4\xa1A`\x1e\xf1\x00\xfe\xd7lj\xe3$R\x1b'K\xe48\x14)\x04\x02a\x8c\xe4\xae\xc8\xa5\xfb\x82\xf3\xb3\xd40\xd5vH\xf2\x94\x8c\xd1\xc0\xfa\x8f\xaeO\xbd\xfb\xf3\xdc\xd4\xc25\x81\xb6r\xffD\x113e\x9be\xab\xb0\x1f\xef\xf6\x8a\xbake\xc2\x1f\x93\xfa\xa5\xe9b\xb0I\xeb\xa3f\xa0\x8d\x02N\x88\xe3\xe7f\x01\x0bYQ\xf1LR\x9f\xf9F\x9a\xcall\xf2UN|c\xfek\xb7\x08\x8d\xd5K\x00M)(\xd4C\x11\xd6\xb3\xd1\x19\n\x08xyAb\x17'\n\x08\x19\xaa\xe4F\xbd&\xaep_\xdeV\xdc\x1c\xd4\x02\xb9M\xe9\x08\xbd\xec\xbf\xb4\x8f{\x12\x98\xa6\x10&\xa3{\x92\xd9j\x91zo\xf9/\xcd\x84p\x1e\xc5\xb7\tI\x84\x0f\t\xdc\xb5g+\x94\x84\x82\xc6D\x1f\x13)\xb3\xa0\x8e\x8d\xba\xd2\xc7\xe3\xe9e\x8bS/\xd8*6\xd5w&\x86:\xa6\xe8\xdd\xd4\x929\xe3/\x8b\x8flrj\xa7S>]A\x8a\x12\x9apC\x1c\xca\xf8\n\x1d\x93\xd8\xb7\x89\x7fF\xea\xcf\xbco\xf5T\xbb%\xbb\x12\x04K \x8a.6s\x03\xed\t\xda\xa3\xa6\xc6\x920\\\xc2\x8bm\xa8\x9e\xa0\xa7.\xca\xb1\xdc13\xa0(\x8dP\x12@3\xfb \xb0M\xaf1\xa3\xb8vMb\xab\x88E~\x1b\x81W\xda\xfb\xed\x97?k\x17X>\xca;o\xb3]H\xe7\xf6>\x84\xd5n\xaa\xc8)\xb7\x89\x0f<\x9c\x0c\x0fZ\n\x14\xfel\xcfk\xa0\xba\xec\xf0]\xc2%\xa2\x9f\xb9\x93\xdc\x8e\x7f`-\x08\x7f2k\xad\xc9\x1b\xbd\xc3\xd3\xfa\x06\xc1q\"\x13jR\x9e\xa2N>\x18\xfd\xa4]bb\xc7b\xd4|\xe4\x1b\xa4,\x9a\xdb\x80\xf3\xf7!\x1d5\x8f\x9d^D\xca\x97\x8cCn\x80\x86O\x94\xf5\x8b3\xb5\n$\xe7\xa2\xaaI\x84\xf0\xca\xf3#Q\xd1\xfe:\xb6\xa9\x15\x98\x05\xea\xb6g\x81(\x00d\x15\xef\x87\x80\xd2iU\x96\xe3Q\x9a\xd7\xa0\xc6\xdbJ\xa8\x13\xf7[,:\xe2mQ\x1c{5x\xeb\xd6\x99\x92\xba\xea\xad\xd7\xa8\xa1N\xd6\xb3u\x08G \x8co \xc1\xe2\x93\xe5\xfc0/\xcd\x9d\xb8p\xab\x88\xb1\x80#\x12\x00$\xbf\xc7h=\xf6\xdb\xb2\xff\x02W\x93v\xbf\x867\x06V+\xc4\xe4\xef\x93\t\xac\x0b\xc8&\x87\xd8\xf1\xa4\xf4b\xac\xd4\xa9\x97\xd04\x89 \xbcWK\x03\xc4\x8dOu\x80\xd1\xeb\x18j\xfaXK\xb6\x02\xb4\xd4M\xf7\xce)\xb1\x94\x90;\xd4\xeb\x9cX\xabG\x9fF\xf0\x10\"$\xe9\r\x91\xa64\xf8\x15f\x0b\x86K\n-1\xe2B\xc4\xaay\xeb\x05\xbfm\x0c\x8d\xac+T\xb4~k]v\xe0\xc9\xc8\xa0\\?\xd6\xc3o%g\xa9T\x97\x03\xb1\xa5\x88\xab:\x9c0\xc6\xb8u\x14\xb4=v\x91\xec\x01\xa63\x83\xb8\xea\x9b\xef\x0fQ\x03!p`\x9a\x14\xae\x19\xf2\x85N\xd6\xb4\xb6?f4\xc6\xa2\x89\xa1\xef\xae\x8a>\xba\xfa\xb8\xf4\x9f\xd5\xd3\x14\xeb\xb4:\x0c\xbc\xe9Si\xa8\xff\x19\xb3\x0e U\xbb\x0b\xc8\x8c3\x83Oa\xd4@\x15\xcf\xb5\xda\xbdXMt\x1f\x15\xf9\xbc\x1b\xe9\xd9\x9b\xa21\x11\x9bI\xc4B\xdcME\xe2\xc2\x04\xeaI\xf0?|\xf0\x99V\xde\xafL\xe04~-vg\x15\xbc\xed\xc4\xf63;\xa8\xfa\x1a\x1d\x16\xdc\xf2\xb6I\")\xa0$\xbc\x86B\xbf<\x97\x88\x83\xae\x13\xa7\xb8\xe9\xfb\xc0\xfb\xe3\xbb\x95?\x1fH\xfd\x9ab\x99\xb6|>\x08\xb9_DN(\xb8n\x9c{<\" I]\xd0F7;N\x19)(\xe3P\x80\x7f\xae\x12\xe5Y\xb20S\x90n\x1e\x01\x88}\xcb\xfbXC\x9d\x94F\x1a\x1a5\xda\x85\xc43\"iH\x06\xb6\x82\x00\xdb\xa5\x96\x90\xa4|\xfez\xc4\x9a:h\x04g\x0f\xc9+\xc6\xcac-\x90\x00'\x17\x8e\x0c\xc8\xb8?\x90e\x02\xc3!\x15\r\x03\xc0\xb2\xf5\x17(`\xac!\xdf\xfe`\x92(\xeb\xf3\xf9\x8e\x9c7\x00nGo\x18~\"\xfb\x85\xcb\xfa\x0f<\x93E~\xcd\x80\xa8\xd2\x96\x83!\xb3\x80\xcd\x81\xde\xdc\x9b8\x03\x04\x80^\xbbV\xcce\xe2!#PD\xaf6\xc4\x1f\x92l\x89\xae\xc6\xa6\x12\xf0PY\x9d\x11\xb5\xa0\xca\x14\x8e \xd1\\\xcb\x14\x84\xa9\xdd\xba\x16;\xdc\xe8\x8c\x02\x1e3\xbb\xaef4|!\xc4\xb5K\xa6f[e\x12\xc5\xe73\xca\x00#\x81\x07\xcf\xc6\x98u\x91\x12\x14w\x04\xc8\xe5\x82Z\x1du\x06\x04\xd6\xc2\\\xca\t\xb5\x0cx\xd2\xb5\x92\xac%\x9c%\xe4\x03\x0b)\xb0I_g\x9e\x91\xa6\x04\x01~2q\xf1/W\x90P\xb5\x88\xcf .\x97Y\xda\xd4\x920\xe6\x9b\xb0j \x1b\x16\x0b\xc7\xec\xa5J\x003\xf7D\xf5%\xf2}\x84\xb5\x12\xbe\xb4W\xe8\xfeii\xef\xbe\x1c\x07\xb7T]\xeb\xe2\x18s\xc8\x8f\xc7\xee\xe7r\xd6\x84\xc8\xfap\xfb\xa7\xb2\xf4\xa3G\x9c\xa0G\x98\x9d\xba\"Z\xbb\xcb\xdb}\xd3\x99\x07\xf9\x02\xa3'\xb8 \x93\xafs\x88)\xb2\x0eB\x075\xc9\xa6u2\xd4\x13\xae\x19\x12\x14\xefE\x9f\xb2&\xd6\xfe\xa8\xabY\x0b\x1ac\x18q\xfc\xb8/\x95\xc2#f\x8e\x8b\x7f^e\\ \x0b\x96\x08\xb5\xa6\xd7\xd9[\xfe\x88\x8c\xffM}Z\x13\xd8\xff\x8a\x16J\xa3\x89@-\xdf\x9721\xf7\xfa\xb2\xd2;\x00I\xc9\xb0>\xf8\xd8\xee2\xa3\xeb\xbb\x0b\xe3J\xc8.e\x8e_K~9\xa3\x9b\xe0\r\x8b$\\\x13\xb8\x8f\x1a\x19O\xbb!a\xc3\xff\xec\x85e1\xfc\x98\xff\xcc[\xd9\x07j\x1d\xea\xb3\xb5Z*\xa6g=\xfd\x9d\x1bc\xd20\x88\xde\xa0\xfe\xaf\xca\x08\xa34\xb2\r\\\x01\xfd\x97\xf0\xc3\x81\xd4\xbf\xb66\x0el\x1f\xd5c\x1b\x9d\x96\x06\"k\x9c\xce\x91Iu3\xb9q\x19\xb0\xf5\x08\xcdc.\x04\xfd\x7f\x85\x1d,\xe5Jb\xab#^\xfc\x008\xb9\xe5\xf5\xb94P\x9bk\xa9\xd1E\xbb`\x02O\x9e-8`\xd0\xe3\xe80<#\xcd\x8a\x03\xdc\xfcT\xf3\xc0\xd19r\x81\xfc\x94\x9f\x7f\x95\xab\xad\xaf\xccpN\xa9\xc9v\x7f\xf9\x7fF\x8c\xbc\x00\xf5\x99\xd1u\xb5^s\xa9\x8f\x98(\xca\x187\x9a\xd2c\x82~\x04\xea\x97/\x19\xa1N\xf2c]U2a\xd7\xbe\x83\xa0\x82\xa2w\x11&RV\xa4/\x94$]\xeb.\xd9j{$\x96\xe8\xd9\x82\x81\"\xd8\xf3\xc9\xce\x89\xdc\x00=5\xa5}\x15t\xafc\xb0\xba;\x1c\xdb\x94\xc1\x0e\x8a9|\x05U&\x1d\xa0\xf3\x19\x89\x13\x8f\x87!\x88\xac\xd4\xe5\x99\x00Q\x80\x11'A\x12\xa3A]gJE\x9f\xc0t\xc1c\xcf\x98\xa6\x8a\xc3\xd8\x8aF\xbd\x00\xe1\x01\xaf\xca\x98*b\xb0F\xfd\xefP/&V\x00\xec\xb7\x0c\x95\xc4\xe6\x80:\xb7W\xa8\x9b\xce:\x01\xb2\x90\xaa\x9f\"\x14\x05ul\x90\xc9~b\xa0\x1c\x9f4:Q ~\xdfh\xcec\xb2(\x87\xbb\x1b\x9a\x92\r\x97X\xed\\\x0b\xe1\xec4\xbb\x9c\xe7\x89\x1dz\x94x\xfe\xa6Rx\x12\xc3\x86z\r\xf3)\xce\xf0G\x02\x1aG\xca\x87\tl\xc0\xac\xd0\x92\x1c\xf9\x87Kny\x8c&|\xf6T\xe4\xd1Sn\xd3\xf34w\xee%u|\x86\x85\xceQ\xe1\xd3\x80\xaak\xf2W\xde\xda\x1b+\x18\xb4\xd9\x86R'$\x0f\xa8\xd2\x17\xc9b\x15[\x8d\xf1kd\xc7\x08s\xda\xf3<\xc1\x1f\xe7\xd1.l\x0fmd\x00\xe9f\x94p\xda\xbeE\xb8>\xbdKa\xc7'(\xedIs\xc7\x8c\xe0\x92\xec\r\xfb)\x0c\xdbJ\x80\xf8\xca\x07RP\xe3\x94\x1c\x86;\xa6\x1d\xa4\x1cs\xc3\xd7\x92\xe4\xbb!\xde+\xce\x1e\x04\rw\xac+\x832\xaa\xbbop\xb3f~\xc1\x9b\x86\x91v6\xc9\xfd\x16\xf3tX\x99d\x04Q\xc1\xf4\xe4]n\xb9B\x14\xcc\xb9\x02Q\xd9=\xe9M\xaco30O\xacq\xb9;s\xfb\x01\x1cT\xe7;\xc2\xd2\x0b\xa3\xd97Y\xb9\xa0\xcf{\xafdw\xab_\xb7\x992\x81\xb3\xb4l\xfa)\xf9_\xf9;\x7fO\x94C\xe8\xaa\xfb\xa2MT\x8f\xdf8\x96uV4\xc1\xf35G\xcbj$U\xd6\x1f#@\x87M\xe1\x15B\t\xa7S\x1a\xa5\r\x98\xc2\xf8\xbf\xa8%@\xbevYj\x85\xa8\xf5\xe3n\xd0/L\xda\xed\x19;k\xbb\xb5{d^\xc2I\xff\t\x0e\xf6d\xcf\xc3\xcb\xa9[\x9b\x04\xe9\xba\x0flj-\x86\xd8\xc41\x9bA\xd0P\x83\n\x103\niI\x86S\xaeK\xf5\x8f\xf5\x89\xde\xc9#\x97\x98U\xb3\xa2d\xde6\x0f\xcd\x08\xd3\xb0SA)\xdf\\)]\x9f\x90\xd6\x84*\xbc\xe8AY\xb7]\x05\xe6\xc6\x8b\x96\xd8\xa1\xe8m'\xe74z\x0e\x87\xb3\x814e\xc8Aw\x07\xec\x8ah\xe5\x9b{\x0f\x8a\x8cG\xaao2\xd4A\xdfA\"VZ@\xc3^\xe3\x8b\xc8\x03\xca\x99S1g(\x08\xe9\xe7C\x8aR\x9b\xc4\x9d=YQ\x87\xd5N\xd5\xbf\x1a\x13\x84r\x03\xc7\xc9$Q\x805\xedWv+dZA\xa5m\xd3\x11*\r\x1f\x00$;\x99g\x06H\x00\x9f\x93\xfa\x16\xda\xaa\x99r\x91\xc2\x14\xfbmm\xfafn\x0c\x82|\xb6t\xb8\x83\xd7^A\xc4\xe4\xf0\xbc\x98\x17\xa9\x17\xe7,\xd7\xc9L\xfa\xa0xH\x95d\xa6\x82\xe8\xff]\x11\x11\x9c\xa8:\xe6~\x1f\xc0<\xc3\xbc\xc3\xe3\xff\xd0\xa0\x8b\x98\xde\xa8\x9d\xf2y=n\xa6xj\xc3}\x04f\xc7\x06!\xb2\\\x19M\xcd\xb2\xbaH\x84!\xb9\xc7\xea\x1a\x8fi\x7fh\x06\xf5{\x9dYg\xa0b\\<\x9c\xe0\xc4\xae`\xec\x17^\x01q:zn\x9aJ h\xae\xb8\xbe\xad#O<\xc7\x83)\xe1\x86,\xd9}\nM\x05\xd2\x86%\x1b\xfb\xfb/\xd7\xd9?\x1fD\x8c\xc0\xfa\x7f\t\x1c\x81\xc9\xa3\x93~\x1e\x8f\xe2\xddc9\x04\xb0\xb8\xe5\xee\x1f\x88\xedaq\x86D\x9b7\xc4\xdc\x99x\x9c+?8N$w\xc8\xa7\x17\x0e\x00\xef3\xe1\x8f\xfb\xedp\xca\x82!\x92H\x08PE\x17Ot\x13\x0c\x01\"(\xd2\x1b\xbff=\xd6\xf0P\xed\xed\x83\xec.\xda\xb4d\x02\xb3v\xf6k\xef\xa3\xfc\x14\x82\x16\r\xb5\xe8quE\x0bE\x16\xedq\xca\x97\xbf\xbd^\x92\xe1j\xbc\xf5\xf0\xfc\t\xf8\xa6\x9a;a\x18\x10\x04\x07R\xa3G:qQ?Ee\xf5+\xd6\x7f\xec\xe9\x1e1\xb5[\xe3h\xd1\xdcY~\x8cj\x12\xb3\xb9\"\rj\xeaX|\xbe\x9ej\xb9'\xc5\x9c\xfcE\x9e\xfd\xe7E\x95\xab\xff\x87\xc5\xb6\xe4J\xfe\xe3s\x04\xc5B\xce,\x01H\xeb\x04\x03\xc3\xe1\x1a\xa4*\xcdnq\x99\x87\xbb\xf5\x92\xdbf\x94~z\xdc\x14]h\xd2\x91\xb1\x8b`w\xb4o\xd4\xc2tv\xfc\x0b\xde\xe1\x81D\xcf\xc9J\x91G\xb7\x07X\x0e\x12\x1c\xde>K\xb9!\xc1\xeb\x9a\x8fF\xec~\xdc\rF\x9e\x10\xe7;J3\xcc\xdb\x97\xfe\x03\x8e\xdf\xb7\xa4Ax2G\xd7\x8d\x08\"\xf6\xea\x03\x8c.(=^9\xdf\x12\x95\x10ME\x97\x0e\xda\xe7I\xdbcw,\x81\x16\n\xcdW\xe9\xee0\x01M\xb3\xe0\x8d\xc2O\xc2\xd7\xee1f\xbf'y\x1b\xf3*\xb68\x01s\x1a6:\x0b\x80-\x12\xbc\xc8_\xc6\xfc\xbfe\r\x08n\x81\xd2w0\x0b/\x94\xef\xb6\x02\xf9\xc1\x04\x19\x05\\h\xb7x0U\xff\xc7\x9e]k\x9a\x9f\xe4\x17\x18)S\x13\x89\x80\xfc\xb4\xb6V\xd2\x1f\xe8D\xcb\xd4\xec\x08\xcb5PA\x05\xf8rwb\xdd3\xe7\x19N\x9f\x8fw\xe4\xfdK\x97\xc6e\xb5D~\t\xc4\xfa\x07\x0e\xfd\xa9S\xbd\x91\xf1r\xedB\x86\xf1\x96\xb4\xff9\xa8|\x14H*\xf6W\xd8\x9dO\xb3\xdf\xf8\x8f\xab\x0c`Z\x9a\xcf\x81 \x06\xff\x9f\x8c\x9c\x11wCb\x8a\xbe\x89\xcd[wv}q\xc5Ah\x8e\xb4>\x01\xb6\x0b\x0e\x84\xa8\xc4\xdf\x9a\xa8\xfd\x99\xba\x80p\x9a\xc2\x8f\xabk\xebq\xc1\x96\xbc\x972\xb8\xf7\xed\x80\xd5xfF\xec#\xe528\x14\x97\x08\x95e\xb2~=\xb1\xe6j\x83<\xe9\x9b\xf0\x12\xcd\xe8B\x8e\x96z\xca\xafQ\"4\x99\xdc\xa8^\xfe;\x89e\xdd\xd6\xb4G\x17\xea\x1a\xa3\xbf%bb\xca\xa3\x05.r: \x10Z\xdf\xd4g\xb3g\xe6\xb2\x96Nw\xed_Z\x16\xa5]X\xa3w\x14f\xe1\n\x9d:\x0c\xf82\r\xbep\xa8py\x97U\xc6\n\xe8D\x89Q?\xc5\xe2\xca}\xfc'\xc9\xf5\xf1\xbc\x9b\x94\xb3^P\xbd\xc5.'\xc6\xc5\x11\r\x86(\xee\x95>|\xfbY8r\x89o{\xe4\t\xb9C$`\xaf8\x7f\x16E\x16\xac,\xa2\xabue\x86h\xcapa\x0b`\xad\xb6\xcf\xd83\xa4\xb6\x11\x9c\x8f\xd7&\xd9\\Y\xfdo\x1a\xed\xf3\x02\xca\x9c`E\xe3\xc8\x16c\xd0\x13\xbc\xe6\x9c8\xed@\x89)\xefA\xfa\xee\xc3\x9ej\xe9\xb2\x05\xc0\xaah1_\x0c\x03\x1f~\xb9/T\xb6\xc0hM\xe4S`\xc48[y\xee%2\xa9\xd0\xf8\x1fs|\xba\\\xd5\xad\xf4/\r\xb2\xd2\xdc\xf0_?\x83\xd9\xc6\xa3w\xb7\xfa5\xf1'\x1a\x8e\x1c\x92\xd9\x12\xf7H\r\x11\xb0{\x01\xc9g\xee\"]\x1c\xadBr,\x8cS}\xcb\xf6o 8\x82Ca\x80\xa8:}\xce\xa6\xf4\xd3\xea\xa4\xdf.\x16Y\xd3\xe8\xb5\xee\xe5{}N\xb3\xb4d\x8amq\x8a\xa4\x9f\x15\xc8/l\xe2\t\x96\xc5\xe8*\xba\xbe\x1f\x1f\xd1\xab+7\x01(\x9e\x9b%\x05wX\xff\xe1y\xd2\x8e\xf0\x9aB\x02\xfcz\x00~\t\x11|\xb6\x8e\x94\xb9=\xdc\xf8\x83\xa5C\x14\xcd\xac\xad\x83\xe5\x9b*\x0f\n\x8b\xc4\xfc\x14\xefW-\x0e\xecVs\xae\xe0\x86\x83\xd1B\xbe\x02XN;xC3V\x1a\x10\xea\xbaVM\t*\x00\x92\xa7\xb5~BB\xf2\xb4\xd3U\x93p\xbfd\x16%\x9c05\x84fN\xdb\xf9\x1b5e\xa0&\xad\xbcsNuY:l\xd3ib\xb7D\x83@\x1c\x9dK\x9b\xf0q\xf2o\xb4[\x97o\xddUy\x9f\x93\x03\xff\xb9\xec\xd8Q\x8e\x11Q]\xdb\xe3zz\x89\xcb\xca]Z\xd3\x01\x02\t\xc1o\xfc\xa9\xbd\x1a\xf9\x8a\x85(9\xbf\x8e\xdd\xb8\x9cm\xb6\xda\x95\xe4\xcb\xbdel\x7ft^G\xa8|\xfe\x9f\x90`\x9c\xad\x87W\xdc7\xdb\x887\x11w{\xb2\xae\xbbtt\x06\x81\xb4\xec2\xbcz\x8a D\x16\x0eO0Q\xc0\xd9\x84\x8a.\xe5Q\x9d\x8e&\x9fa\\A\xfb@\x86\xf7:\x82\xbd\xf4\x13Z\xeb\x86:QJ]?D\xa9\xa8g\xb4\xc1\t\x87;14\xb6\xe2'i?I\x1eHs\x94Z\xe1\x19\x7f\xb2\xf5\x90\x9eK\xe9\x1e\xed\xd7\xe3\xe6\x0c$R\x88\xfaB\xc8\x92\xde\x05@\xda\x96\x92G\x87lE(\xaf'\x9e\xae\xfaR\x1e\x0bC\x9eH\xf7\xdf\xe3\x9f\xe0\xf9T_t\x8bB\xcahh\x81\t\x98\x82\xa1j\x17R\x1f\xf1fTl\xec\x91A\xf1t\x1aR\xb7\x7f\xb3\xbcBZ5\xb8\x1co\x9eN\x1d.g\xee\xf7$\x85\x87f\x90).\x10\xb6\xf7q\xf9\x94zP\xb7\xdb\x9b\xd39\x1d\xc0\xd6\xfe\xff\x07x\x1c\xfb\xaf%\xbd\xbc\xc6\xba\"\xf6|\x10\xd75\xc3+\x18\x1a\xfb\xb4\x11\xed\\\x8fh\xd9\xc0\t\xa1\x17\xccZ|Z\xb1\xb8\x8e\xc9#\xf9\xd6\x8b\xbf\xdfn\\\x96\r\xa0=0\xbc\xe8\x84\x0b\xef\xeeR\xfe\x1f\xf7@\x02\xbbR\xe9\xbb\xcb>\x8fS^\x0f\x92\x7f*\xf7+\xcd\xca\xdc\xc8p\x06)\xc1 \xcdz\xab\xcb8B~\xaf{}\x19\xc6\xeb\x8b\xdd{j\xe0\x01\xe4l.\x19\xd3T*\x8d\xc7H\x07k\x8b\xfd\x8eg\xcd\x89\xaa\x8a\xe6\xfb/E-X\x8a\x89\x02\xa2\xcd\x13\xacN>\xbc4a\x18W\x02\x95\x9e\xa4z\xff\x05\xf5\xa9\xb0,`*\x11}\x1cz)1\xf1\xe0\xb8\xc64\xc8\x032\xcc%z\x80\xb1\xec\x7f<\xc4\xfentJ\xd1\x10\x90\xab\n\x96E\xe2\xa2\x00L\x1dO\xe2\xaet\"B\x0e\xf4\x8d\x8c\xb7\x8fA\xbe<\xcb/z\xd6\xae\x02(\xb8\x9dL\x85?\xe7T\xba\xd7\x961\x8d\r~\xa0\x9e\xe0\x12\xd1-\x8dc\xb8\x06\xc4\xa1\xfe\x1d\x8f\x03\x86\x9a\xeeh\x1c\xdb\xb8\x96\xfcc\xfa\xd4\x13\xfaX\xa4#N\xd2\x0c\xfe4\xbdB\xb1v\xa6>\xbdE\x9c~\x1f\xc3\x17u1C_\xa5\x84d\xe8\x9f0\x9f\x98A!\x16+Go\xe6s\x95EA\x8av\x1c\x1d\x83\xabZh\xef\xe2zS,.\x1d\x91\xfe)\x19l\xfeyAR\xc3\xa1>\xe6\xb1\xef\x9d\xaau\x1f\xf3\x86Y\xf6%L%\x932T\xf3\xbc\xcckX\xf4\xebGa\xffV\x92M\xd0C\xd4Kn\xee`\x98\x84;{P(\x9be\x01;\xd6\x16#88\x0c\xcd\x97\xd7\x14\xdf\x0c\xa0\xedDc\x82W\xe6j\xa6\xbbH\xa5\x9d\xcb\t@\x0b\x10\xfd)\x9ai:\xd4\xe1\xbcU\xfdLs\x9d!\"2iRI\xe5\x93\xa1'\x86\xd8\x90\xbe\x96\xc5\x04ul\x15\x95`\x8b\x17\xeb\xef3U\xf5[\xbcV\xe5\xbf\xfc\tq}\xb9@\xb9+\x80\xb2\x02&\x7f\xc7^#\xa3\x8c2\x862\x19\x12\x97\xbd\x06\x86i\xbck)N\x05\xe7A\x13\x9d\xf0?\xd0\xe0\x10\xe7Y\xd0\x83\xf5\x1e(\xaf\xaf6\x04\xb6\xe5\xb0E\xa0\xa6\xe1\xa7\xcc\xd1\xbe\x89\x9f\xf1 b\xee\xecp\xa8\x08\xdf\xdb}1\x93\x97\x984yG\xe1\xf3\xb8\x14\"4\x1cfL,\x953\x88O\xb4\xfcv\xa2\xae\x9e\x10\xc8\x91\xa7\xc7\xcb\xff<\x90\xc0ojKK\xf2\x16\xfc\xf6rm=p8SJK\x1b+oey\xedp\x8e\x81\xa9\x9c\xaf\x12x\xc3\x8c>L\xd1\x82\xe2\xbb\xc8\x16\xc5\xf4\x0eQ\x9f\xd6\xf8\xf55wu\xc9\xf8\x0e\x0f\xf183\xa2Mc-\xc5\x80Rpu\xcbJb\x84\xb1\x1f\xc2\xb9\xc1\x07\x96\x9f\xe5n[N\xc8\xafW\xfb}2qM\xe2\xc9\x8b\x19\xe0\xc2\xc6\xc5\xc4@\x88\xf7\xca\x88\x9b\x0cC\xd0*\xeb\x16\xeb\xef/\xb3P\x96\x1e\xf3\x8e\xc9\xbf\x975`%\\\x04\x15\x91\x89TV`\xc1O\xea\x89E=7\xfc\x9a.\x98\x8c\xe7\xd0\x86\xf5+\xd7\xc0[g\x0e\xab\xe1\xed\x07\x10Q\xbe\xfc\x93 \xd7;5\x93?\x85\xa41Y-\xd23I\xf9\xf8\xb2\xc7\x7fX\xe7x'\x87fF\xbbp\xeb\xda\x0f\x94t^\x84\x8bz\xeb\x1b\xaf\xba\xb9A\x95\xd8\\\xca\x91\xea\xc3I\x97\xd4\x86\x8d\xffM\x9b\xde\x82AA\x9f\xab\x17_\x9d\xd8f\x87\xc3\x93(U\xd8\x8a\xfc\xf7%\xd1\"\x0c\xcb\xc8\xa2\xbe\xe3\x0b\x11\xd0\t^\tHf\x15\xac\xa7\xd6\x0ekDq\x036O'\xf6\x86\xfdS[{u\xdf\x97\xc7\x96\x9b-\x88\x9f\x86\xece\x8c\x83\x8fi\x9c\x8dw\x04\x13\r\x1fP\xea\xa6\n\x94\xc3\xf3\xcfvw\xe0\xa5R\xcaf^\xf5u\xceU\x85\xd0\xb3]\x85\xe8y\x8di\xcc\xd2.j\xc7\x97G\x1f\xd8>L\x18\xd1\xba\x04y\xd6\x83R{y\xc4aqB\x0c\xc8Rm\xb7=\xf6\x0e\xc4\xa8\x98Y\xe5\xd6\xa04\xf7c\xc9a\xd5\x07\xca\x11\x80\xcex\xcbb\x97#2\xec\xf3\xca\x03\xf7\x95\xcb\xc9\xd3=\x8ed\xdf(\xd2Y\x16^TiJ\xa5\xa0\xaa\xb9\xb3q\x90\x9f@\xb0\xb0\xe1\xc4l\xa3`C\xcd\xe5\x864\x064/\xd0%\xd4\xce\\\xfa\xd0P\r:\xb6x\"\xa8lsK\x06\xcb\xc2x\x83\xb7[\xf4.d\"\xf6\x02Q\xf8X\xf1\xf8g\x1cc\x03 R\x1b\xa7\x15\xbc\x97\xb6\x0f\x7f\xd0\xf7\xcb\xea\xfc:s\x1ay\xdf\x19\xdd\x12;\x02T\x8a\xf3\xa2\x84q\x04\x9bi\xaf\xc9\xe9*\xf3\x98\xe1#\xa1\xf9\xe8\xb0\nl\x8c\x12\xee\xc1\xcfH\xa3\xb3'K\xf4Ot\x19\xacY\xd0?=\x90\x0bV}\xf3+\xc8;l\xb2\x00\x14\xde\x04\x7f\x15\xed\x1eP\xc1-@\x84\x17\x7f\r\x95\xf59\xf3K\xbb\xb8\xa8Y\xe7\xc6\x976\xb0g\x04\xfc\xbe\x15\x9a\x9d\xb6\xa2yfW\xb1Y\xab?\x8f\x9c\xe3\x94\x07\xa8xP\xe5\xbe\xb8\xa3\xe9\xf9c\x88\xda\xb1\xc4\xbd@\xab\xdfe\xb0R\x99\x85y\x808\xdf<\x99\x1c\xd8\xc5\x00\"\xc3\xfd\x92\xf5\xd9\x91\n\xdd.a\x11\x9a6\xe3\x15=hyB\x96\xad\xbe\xf6\x84\"\xf2\xa0 \xa1Ux.\xb2\xc3\xba\xcc\x14x\xf0mK|\x1c\xd9\xd5m\xba\xe8\xb3C\x1di\xd3\x8f91\xaf\xd5\x8e\\\x0c\x19BM\x13c7\xc7\xed\x1c\xf7{JBy\xb6i8q\xcdT~^\xce{\xef\x91$\x85\x883\xc2v\xf1\xb0\xf5vS\xa7\xe0\n\xc5>MTc\x9d\x7f\x01!\x14\xf3x.\xee\xbd\x10#o\x18\xba\xdc\xf9\xf1\xdd\xc0.\xf3\xe3p\xb5`\xd7\x97\xe79\xc1\x8bP\xf4\xce\xc2\x1c\xfa\xc1\xa94\x7f\x1e]Q\x7f\xfa\xdf>\xa7 S'\x8e\xe8.\x8b\xc6y\xa1?\x1c;\xac'\xd00\x0cP@\xe4R>\x06\x15\xb5\xb4\xce\xe8\xdc~\xd4\x8bI4\xf6+\xe5\x82\x1f\xed\x04\xa7\xb8\x9a\xa9\x8a\\\x18\xc6z\x08\xc9\"\x97SE(\xa4KH7<\x8c\x06\xad\xb6\xe45\xf1\x0c{\xff\xad\x81\xe8\xf9\xb6\xe7\xc5\x90\xda\xb9\xea\x05\n\xd5\xd2\x0b9\xcb\xc9\xce\x89\xe0AT\x1c\x0b\xb9]\xb0\x07\xcd\xddWe)B\xb39\x9f\x9a\x0b\xce\xb4<\xa2\xef=\xd0\xc5\xfb3\xf6B\x9d\xd6\xb1\xf68\xff\x16\xd19\xc63\x81M\x89\xf0\xf67\x9a>(gzO\xcdt\xc7\x91\xe3\xbd\x81\xcc)\xa7\x14\xba[\x99\xcc\x92\xbb\xfa\xce\xa1\xd0n\xaa\x91b\xad\x1cb\xfb\xc3j\xda\x9f\xf4\xcf0\xb7@\x8e\xf5{\x14\xedU\xbc\x1d^\xeb\xe8v\xb5R\xc7T\xadR\x04iP\xf5\x7f\x9c\x0e\xf9(w\xd1\xa39`K\xea\xff\xe5\xb4\x7f\x90D\x0e\xf8\xc7\xeb\xc5q\xe8\xa5=\x94\xf9p\xca\xa0\xcf\x01\xeb\x8f8\x87\x00y\xfcm\xdd\xcff\xb8N\xde\x02Lv\x94\xeb^$\xc8Q3\x90g\xf1nMmC\xe31\x81\xb5\x10\xcb\x16\xab>\xef\xf3l\xe5\xc7\xc4>x\x88\xb8\xb36\x1be\xa41q1}^\xf1i\xa4\xde\xff\x10\xc1\xaaJ=\xa0w\xdb\x07R\xd9N\xed\x87\xb5\x04\xa8\xf2we\xf9\xca\xbc\x14\xf5\xb3\x14\xef\xf8\xc9\xcc}\xcc1;\xba\x95\x9d\xe5\xc2[#\x86\xbbJ\xa1\xa0Z\x04\xd11\x00\xe8\xbe\xade\xb6\xa3\xfaaG\x98\xa5Ad\x81#q9\x03d\x9fr9\xdf\x12y\x1fP\x8d\xa5\xd3XYA\xd4\x8c4cA\x8d\xa1\xc7]?6\x176\xa0\xc40\x1c\xd0/\x9an\x97\x1fUW\xac\xb6\xc5T\xbf\x15K\xac\xedoz\xd1e\x83tc\x99\x8f\x93\x108{\x0e[\x82M\xa1\x04\xd4\x1b\x8b'\xf9\x14\xf1\x13\xa4\x16\x83\xc9B\x9f\xaf7\x9b\x04\x9b\x15I>\xd2I<$$|\x823v\xec\x0c\xdd:%\x88e\x1f\x9ap\xa9\x97\xf79\x14\xbe=6t\x99\xc4>@}w=dn\xd5_\x90\xa3C\x91\xc5'\xd1\x8f\xaf\xbb\x05\xc5\xe8\xa2\x80\xf03d~\x0c8\xa9\nm!I\xadvX\x0f#\xdd\x0b!\x0eq\xbe5tP\xfc.\x16\xe8D\x94A4\x87\xa4\x17Y\xee&\x1f\xaae\x1d\xd3MCAG\x1dg\x82|}\x8e\t.\xdeuO\xd1B/\xe3~\xc5\x88\xa6\x156'\x07\xe2\x06\xb7\x07.\xfb\x8f\x1d\"3ju\"7\x13R?\xa3f\x16\xf4\xdb\x0c\xbe\x8b6\x8b\x8a\xaf\xd2\xa6\x9dm\x8fUg\xbb\xb3M%\xff\xcaG\xb2w\xf2\xec\x03\xb9^?\x98Xeiyh\xe0\xe1\xb0|\r\x1ax\x1a\xd4s\x03\x7f8\xfa\xc7qKk\xb8\xb5`v\x1e\x81\x10\xbe\x81\xff\xa9,\x95X_r\xd5\n\xe5\xd4\x98k\x03\xd9R\x9f2|\n\x85\x82!&R\xa51om\x97\xce_\xd64\xfe|\x92\xc0\xb4\x95e;@\xd1)\xdb\xf0n9h\xb8$*N\xe7\xcc\x05\xe1@\x136vs\x1a\xab_\xaed\xf6\xae?S\x1c\x9f5\xdb\x03\x04\x1c\x11\x8b\x97\xa3\x12-\xff\xdao\xd5\xa8!=>|h\\BT]\xd9\x93\x7fK\xfa\x07\x9ch\x9aa\x9bX\xa2X\xd6\xb7)D\xfcs\xc5P\x94\xfc\x05\xb2\x05\x04\x96\xcc\xaf\xeb\xe4\xd2g\\\xbf\x0e,\xfe\x012.{\x00[\n\x93\x00\xd2r\x96ZO\xe3-\xbc\xdc\xe3\xcc\xf7P\n\x19\xd4!x\x0b5\xa9\xe2h\xc7\xce\xb8\xa2\xb3%\xd6<\xd0\x94\x98\xabh\xd1w\r\\x!o\xa1n\x91\x12\xacT\xc3\xa9&Y\\!\xcb\r|t\xe1W\x92E>\xce\xc2\x95\xf0\xcc\x1c\x02\xbbR\xf5z`\x13\x1bh\xbc\xe0?\xd5D\xd3\x1a\x94\x01^N\xaa\x87\xa0\xd2\x19\xa8\xbc\x94c\x93+\xc2\x90\x01\xde4\xb5.\x1a\x05\x91\x18\xab\xb8\xf1\x06$i\xf3\xe41\xca\xf4\xa58\xac\xe9D\xd5\xea\x19\x7f\xf0\xcb/Q\xceWl\xc8k\xbe$\xc2'\x0b\x7f&\xfa\xe5\xc8\xa4\xd6\x0f\x19U9\\\xcb\xa8\x15\x0b\x89\x8cD\xd0\x13\xbe\xbd\xfe9\xf7\xea\x08\xc1\x17\xa3\x91\x97\xaf\xdbN\xfa\x0c\xabV\xdb\x19\x05\xc7\x8ei\xd5\xbe\x83\xb1'\xdf\x96\x03\xa5_\x9e\x0f\x0b\xf1\r\xec\xfb\x0cp\xa3\xfd|\xf8Lb\x80\x98B\xc2\x98\xf3\x91sx\xbe\xcc\xb9\xc1&+\x98Z/\x07\xa1Y\xfd\xedy\t\x9c\x91\x8d\x12\xe7\xf2;\xa3Z,\x99<\xce<\x17\xcfG#\x16\xf1\x9f\x81y \x18u\xea~\xed\x9594\x8e7\xcc\xf0\xb6\xf2#mA\xb0~\x1d&\x00\xa1\xaa\x99P\x80\x1aSs\x01\xfe'Kbr\xebts\xb0\xe7\x08\x93CWW\xbeA5\x9e\xd5B0\xf2\x863aV\xea6\x827\x95\x03\xd9\xb0Di$u\x82b\x98\xf1\xd5\xe1\"[iTVf\tFo36\xb2K\xd0\xb3\x8b\xd0\xe0\xb7~\xb9\xe2\xd9\xf3r\x18\xdf\xe8\x1f\xcaP\xf7:Z\x1d\xdd\xac\xd5\xf4\xbc<\xba\xce\xfd\xf5\x106Z\xd0\x12n\xab\xdc\xce\xc4\xbcz\xf1\x7f\x90X\x8e\x9b=\xae!Y\xcf\xc6\x87\x94\xdd\x91\xae\xdcD\x06\x0f:\x95+y+\xa7\xff\x01\xdc\xb6?'\xcf0\x17\xe6\xa1$NA*\x9cU\xe9sr\xbb\x98O^\x10\x94\x84\x8b\x11\x10\xad\xf7\x89\xd6c`\xd3uX\xb8\xdd\xc7\x86\xb4\x8d\xb7\xed\x1b\xbad\xb1i\x05\xfdt\xa6I\x8b\xbf\x9cw\xf4\xcc\xec\x92\x92\x18?7\x9f!\xfdHk\x90-\xa5\xbd\xdb\xe9\x11\xb6Pp\xe2\r\x16\xc6\xd1\x89\xf6y\xa0|\xd5\xcc\xf9\x99gq\xf3\xb1\xdc\x88kf`f\x8d[\xa8Wx\x8d\xe1\x07\xfdR\xeb>RF(\xd56\x16\xc8\xc4\x9b\x1a/uM\xefe[\x9d\x1b/9\x90\x8cY\xa6\xe1\x04K\xe0:\xd8\xa2r\xde\xc4\x9b\xad\xac\xe6\x9d(\x17\x81\x8f\xc9\x11\xf6.\xb5r\x82\x9f\x83\x827\xc8\xc0\xa0\x9ae8\xb4\xadz\x1d\xe4\x92\xd2\xdb6\xe4,e&\x98\x7f\xa5\x9c\x02\xdd\xb2\xad?\x95iq\x87\xcf+\x10\xfczT\xcb\x90xA\x13Q\x9ar\xa4\x0c{\x02\xb3p\xc25\xf0~\x16\xa4a\xaf\xb91\xd2\x94X\x1a\xbdX\xc4J\xec\x0b.o[\x8a\xd8\x0f`\x97%&\xd8\xd5\xda\xb3\xd0h\x14\xa6\xc9L\xb3\x84w\xe3\xec\xcfV,\x02\x04,,\xbc)\xec\x9d\x9bs\x1cn\x8d\xdb\x8f\x84o\x19\xb53)\xf6\xf2\x97\xb2\xee\xa4\xb6\xb6a\xdf\xa3\xaa\x83\x9f_6q\xec~\x87\xaa1 \xd8\xc5\xe1 {\xfdv4^K\x17\xe1\xb5dg\xa4\xf2\xe9K[\x80)\r\x07\xb9G%\xb7\xcb\xa3\xba[\xbf\xbe\xdfV\xb0\xd7>4\"\xc1\x11ph`[\x1a\xa2\x10\xa0\xb6z\x0e\xbb\xda\xc8\x8e'\xe6\x9f\xa7|\xdc\x1c:1s9\xf8l\xaa`\xecx('\r[ \x1f\xf0\xd7\xa7\xd7\xa1^\x84\xfa\x0cz\xfd^\xae\x8d,\xffub7\x84\xc4\x86\xa3\xea\xc2\x01\xef%\xb5\x84\xadrl\xdd\xdd\x88o ?T&|e\xcf\xbfbI5\x0e\xdcR\x06\x07\x04}\x9c\xb6t\xdcf\xd2\xee\xdfZb\xd7Y\xc0u \xdf\x7f\\\x02\x03@\x18\x01K\x9d\xa6A\xe5!\xb7\x14~\x10\xd1{\xe6,\xbe\xd3\x87u\xd5\xe1/\x07\x197\x01@\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0foCs\x1e\x13}0=\xfa0[\x81h|\xf9\xeaR\xa9\xe3\xf4(\x8c\x018\xaf\xe9\xd0\xa8,\xd4b\xe8A\xa5\xb1q\xc1.+y\xe3\xff\xa8$\x12\xaf\x89\xa7\x9ams\xe6\xcd\xe8\x11u\xff\xe6p\x8a\x8a\xe5O\x08\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f2\x91\x88\xc4\x01\x19\x08/H\x84\xd20_V\xb7\x15\xaf\x90R\x1a\x1b\x16\xcd\x84\xean\xe6\x9a\x89\xc3H\xf0\x9c\xbd\xc3\x95\x18\xf90\xc0\xd2P!fA\xa1\x82\xb6\xa5Wdj\x96\x96\x8c\x1d\x94t\xd6/w\x12K?\xf6\\3\x8c\xa1!\x7f<[\x9d\xcb,\x1fn\xa0\xaa\x8f\xea\t\x90KG\xd0\'\xa7\x9a\x89x\x9e \xf2\x8e\x81\x12\xdd\t\xdf\r\x7fKv\xb5\x89\xa7i\x7fB\x15"\x7f\xe9Y\xa6\xfdY*\x8eX%\xcc\xfcc\x88\xc5d"qH.\xc9\xc8\xe3\xae\xb4\x94\xbdsz\x11\x047\x0c\xf0\x04\x1dWboe\xfeW\x97\xbaD\x81\xa7\x9d\xb4\xfc\x16>\xb5\x05\xed\xd1g\xd5*\xe7\xcf\xd5\xd5\xd4\xc8J\x1f\x859y\xdf\xb7\x1eyu\xc3\xb3\xb4\xca\xa1=8T\xc6B\x17;W\x02\xb9\xdc\xde\xc8\x1f\x88\n\x9b\xb7N\x95%\xce\xc8?\x02t\xfd\xb8\xa2\\\x12\x1d\xd6%7\xe3\xd3l*\x9d\x8f\x93&\xe3?\xc1\xd6\xbe\x14\x8e\xef\x08\xbcM\xb4\xde\xe9\x05\x14)\xa0:W\xebRG\xd7\xde\x1dB\x97Q\xd3\x85\r\xa7\xf0\xf7\xd30\xfcx\xc3ws\x8d\x8e\xf4\x18-3\xc6\xe9\x9f\xe3\x1e\x81\x8a\x99\xdb&6\x8d\xc1\x9d\xc0\x03\xf2\xb7\xbc\xa3\xbd"\xa8\xaf]7\x1a>\x1d\x9cH\xd6\xa8\r!\xa6z\xc0\x117\xb3\x97]PZ\xe8\xdc\xc6\x7f\xf8\x165\xed(\xefQ\xee\x05COb\x15\xbe\x8b\x88\x0fl\xb0WiW\xb1\xffvDdl\xa3\x12\x9cT\\{\xa2\xc3\xad&`\xde\xf0]#\xa3(\xf5\xab\x88\x8ba\x85\x02\xc8\xb3\x1dA\xd20\x0b",\xea\xd3\xc9\xeb?#\x80\xda\xc3\x84\x0fl\xd4\xcc\x1e_m"\xact\x1d\xd2\t:\x1b(\x08\xb6\xed\x92\xe6\xa5\xad\x9b\x84\t@\xa2\x91l\x1a\x90r\x8eTc\x16\xa6\xdd\xfc\xf3#>\x11\xf0\n2,{\x81`\xffa\xf7Jz\x07\x10{\xebh\x90V\xd9j=\xdb"1e\xa2-\xa4\xb4\x82\xc3\xea|\xf8$\x88\x80J/\xa9VU\xbd.\x88\xf7&6\x1d\x18e\xf9\xb7\xb3c\xb2\xe6\x0fvZ\xf4:\n\xb7l\x11\x1f\x00\xcc1\x16\\oQ,\xc4\xd9\xee\xf6\xc4\xf9-\x81n\xf1\xcd\x13DwCg\xbd\xb6\x14\x91\xd92\xb2\xff\x96F&\xc4b\x1el\xb4:\xc5\xbc\xb8\xea@{r\x7f\xf8\x82\xdcgG\xf28f\xc6s\xd5\xa9\x8fH\xe5\x10T{C\xfd\xee\x9b\x1c\x12U\x15 \xf8#\x0f\x95\x85\xcb_\xf5\x1bWO%\x0b\xca\xa1jm\xf2i\xd8\x8e@\xecd`\x93C:\x01w\xbcKrs#\xf5\xd1\x0cp\x1bq\xe3\x95\xf9Q}\xab@F\xb3\xec8*\xfb\x9c\xb9\xa2i\xe4"\xbd\xb1k\x08\xa9\xe0\xe7fH\xf1\xb0-kS\x8bbT\xd4\xe8H\xda\xfb\xe0\x8c\x0b\x8a\x9d\xa4F\x88[G\xe5*\xf6\x84\xb3\xae1\xf6\xc5?\x11Y@|ft\x8d\xa3\x1a\x13~\xd6\x90\xcd\xc8\x97\xaf3\xba\xad\xf6\xdedA\xd3\xae\x08\x00\xf6/s\xd3!dN\xc5\'\xfa\xb6b\x02\xb97\xd2"\x9d\xe6\x9f\x08G\xfb\x05\x1e\xb8,\xe4\xc5\x92\x91\xaaP\xa3\xe4x\x80\xc5\xb0\x14O\x90\x11M\x80\xeb %\xfcs|\xd2\xd5\xf9}\x83\xa6,\x1b\x0bv\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f-r1I\xd9\x9f\xeb2r\xdc\xe0Y\xf8\xe2\xaa\xbb\x94H\xe3e\x89+\xb6\xa4\xca89\x82\x92\x1d\xed\x9e\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f\xe3\xab\xe2\x85P\x08\xd1\xa8\'\x88-\x92e]0\xbf\xa1ai\xa12\xac\xc0hUZ\x82\x98,,\x02d\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f\xad\xf6\\~\xc3{\x8a\\\xc3\xf6@(\x0fN0\x0f\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f\xff\x1dP\x0e\xfeg\xf3D\x9c\xdf\xee\xc2J\xfb\xca\x04\x96\x16\x10\xf10\x17N\x7fL\xf8\x86S|s\x15\n\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f\xf4\xad#UB\x96\xed\xc0qu\x9b\x1cp\x17\x07%\n\x83B\xeb\x81\xabK\x1b\xe59\xa0\x9e\x98\xd73g>\xf0\xfa\xbb\xb7\xbdq\xd1M\x11R\xc3+\x9c\xdaC\xa3H\xeb\'\x04\x0en\r\xf6B\xa5\xb7\xb3\xc5xE\xd8(\xceR"\xc5\x82\x0f\x1f\xa9\x0f\xce\xd9\xd2\x1f\xa5\x8a\xfe\x93\xbc\x02\x18/|\'\\g\xc1\xe0\xf6\xbd\x94\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0fS\xf1\x82\xf9\xdfY\xf3<\xa8\xaf\x18h\xff\xd8\x1b\x19\x19\xcfB\xeb\xe2\xc5k"\x90J4\xe36\x8aI\xe1\xeay\xfa\x1fy\x8a<\xe3\xc4\x8cFIV{\x80\x8f\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f\xf9\x85l\xc3n\x9a=\x9c=\xac\xd0\x9c\x11\x8f\x82\x1cE\xc6\xf3\xe6\xd6\x12j\xfc=al\xed\xbbz\x08\xb5\x13\x9dC\x91ui M\xe2\xbe\xa70\x93\xf7\xa7\xc1Zl5S\x86\x032&k\xd8\xd8\xa7\xdc\xe7\xf3B\x8d~\xe8\x980\xffo\xb2\xbd\x035q\xd3\xf6\x08\x0f\xbe\x85\x0cE\x9ep\xc6\x84\x15\xa3\xc4.`\xad\xc9\xb9\x99\x95J\xbd\xd9C\xa5V(\xe9\xcf\x96\x8a\x05@\xcf4dqi\xca\x92\x9f\x1f\x01H\xdb\xfds)A\x94\x9a\x92\xeftq\xa5\xe0\xf9}\x11\xcfkZ\x81tw\x1d%\xc1\x18\x9b\xde\xf3\x88\x18\x88+:\xd7\xd4\xdaW\xf6\xe0\xe1\xcc\xd2\x83a\xea\xdf\xbe\xc6\xee\x82)1\x03\xc3\xb7D\xd2\x8a\x00\x1eO@tVr\xcaO\xadDl \xd7\xa3\xa2\xf4\xda2Q\xce\xaa\x8d\x7f\xd1\xd1\xfb\xc0\xa3>\xb9\xb4\x8eT\xda\xe9z\xd6\xba\xfdT\xb7P-\x02\xa4\xc9\x8a\x1e\x82\xb5\x11\x8e8\xaa\xde/\x84dD\x03\xa6\xf9L\xd7j\x8f%o\xd6{\xf8Gq3(*%\x01\x1d\xea\x8c\xbabe\xe0[^\xa8o_\xee\xa9\tk\xb25\xbb\x07@\x8a\x99\xb9\xbb\xde\xeb{\x92s\xc5z^q\xa9Z:\xc1vtO\x0c7\x9a\x9cf\xdeA@\xb3\xbfX%\x88\x05\x0b;b\x06\x89\x12^,\x82~\x18\x93`\xaeqjy\x1c_\xb6p|\xef\x16>l\x9f\x88\x0fl9\xe9\xed\xcb\x01<\'\x08x\xfa`\xb5\xd4\x14\xab\x10\xb0\xe4\xa2\x8f\x80On\xb7E\xcb\x81\x84\x86\x83\xfe\x15\x8b!Y\xd7\x83*Oh[a\xc1IU\xa4\xb3\x03\xd8,\x7f/\xdd\xed\x8e\xd0\xf2\xbd\x12M\x1eSK\x1d_\x08%\x9b=\xa2\xa1\xeaD\x99mq;HI\xfd.Zq\xec\xa0\x86\x13&\x02\x0bI\xf8\x10\xd6`\xaak\x02\xdf\xe5\xaa\xba&\xfa\xcdP\xde\xe31\x93SN\x0few\xf9\xbf)\x95\x86\xb9~\x83E\xdb\xf2J\x05<-\xddXj\xea\xfeSw\x7f/\x05\xf7)<\x17i6\xb8\xdb3\x13\x8dv\xfd\xa5\xbce\xae\xfd\xc7\xedH\xc9L0@\xd68Z\xce\x1a\x04\x8f\xf8\xeeD`\xad:\x94\xa3\x8c&c[\xc1\x18\xc6s\x7f\x12 \x04\xb5gZ)\xb5\xe9\x8d(\x92\x05\xdag\xa4\x9f\xb8\xcc5\x0f+\xf1\xb9PF\xef\xa0}\xc6B\xea8N\xe8\xb4\xe2\xb1Le\x18\xd7\x18s\xd9m($m\xebM\xf7\xbd1\xac\x8c\x80\xc6\xf8r[\xae\xf0\x16\x88%\x9a\xef\xb2\xe5\x8e\xad\xd0\xc2\x8d\x96\x80\xb6\x00\xd0\x08,\x8c\xe1\r\xc3W\xc0+\xf7\xa5Z\x82\xffi\xad\x01\xe6B\xcd8MN\xb6m\xc6\xa4jS\\\x13\x92\x056\x02\xb3\x98\x8e\x9e\xbbHt\xe3.\x86\x84\xff\x80\xb4\xee\x94?\xbb7\xd7\xc3\xa8KZ\x85Zj\xb7MK\xb3GolC\xba\x128a\xa1a,{P\xfa:\x05L\x16\x0e/\x88l\xcf\xacO\xb7\xd9\x0e\xc7Ur\x9d\xf5d\xc4\xb8\x9a\x82\x18\xdaQ,\x7f9\xc1\x17\xb9\xf4/\x98;U{i\xcc\x83\xe3\xdeuD\xfdU\x06sG\xc7\xeeG\xa2;5\x17\xf0\xf3\x0b\xe8\x01\x97wg(\x14\xa4?\x96t\xa2\xa45\xe3\x1fiAZ\x89O\x19\x06\xdf\xd7W\xc0T\'r\x0f6\xe0\xf9W\xc0\x9aV\xfd\\\x19\xc5yP\x88\xb8pW\xdbU\x98\xa8/\xbb\xb8\xaf\xf8\xe53\r@\xbe\xbc<~\xc8\xff\x11|\x129v\x12\x9c\x8d\x9c\x95#j\x1a\xe9\xaf\xd7\x9b\xd1\x8e\xa12/\x17M\x84\x9c\xcc\x8f\xa9\x14\xec\x86\xcf\x1a\xfd\x1dE\x14]\x9b\x0cc:\xf2\x84D\xaaMiv\x152\xd2\xcbk\x030\x9ajdf\x8c\x06\xecp\xcc3\x92\xaaC\t\x06\xe2RH\xe1v\t\x0fD{@\x04{\xd7\xbd\x8c\xec\xbd\x8e\x16\xbf/@Hrx\xa0E\x16\x907\xaaz\xca\x8fzl\xaah\xb3\xebc\xe9\x7f\xd0\xe7:\x82\xff\xebE\x7fu\xdc\xb5\xf9j\'\x8eI9\n\xae\x98$\xc4\xee\xf5\x80\xbc\xf50O}Z\x0cy\x0f7=\x9cS\xd6\xee\x95\xea\x85T\xe6\x9a*\xcf\x80\xdc\x14v\x8d\x9c\x83\x1f@\xacf\'gi\xb6\xbc\x05~\xe9\xc6\xce\xb2\xd6\xb1\xacy \x13$\xce\xc4\xd1\x02k\x88\xd4\r\xd9A\x9d\x94q\xf2\x06\x15\xdf4\xf1M\xb3\x02\x84\xae\x83}\xdc\xc8\xc3>S\x01\\\x1d\xb0\xfe\x84\xa3s\xa9j\x8a\x13\xd3\xef\x8b\xea\x90x\x87\xb5\xff\xce4\xf9x{\xad\xb8b\xde\xb5\xb5l\xf9\xb3g.\x83\x9dR\xbeD\xd1\x89\xd6+\xe4Xg\x9d\xac\xc4%\xebP \x1f.\xf5\xe78\x05\xefp\x9c\xf3\x0cJ\xb4G\xd4\x1c\x89\x9c\xd3\tj\x97\xcc\xf3\xc6\x85J\xb3\x0f\xaf\xf0\n\xc0@\xe0"\x19\xeb\x81c>]6(c\xcdH\xbb\xb5?R\xd2\xab\'\x01\xc4ug\xf5\xc2\x89CH\xcfK\x8c\xb2\xed\x11\x87_\x16\xff\xc7\xdcwJ\xfe\xea\xee\xc4\x9d\x9f\xb4\xa2:\x01\xd3 \xeb\x95\x84\xadL\xcc\xd9\x12\xa1K\xc7\xc3`&\xba\xdb&\x9f\xf1:f\xe1\x8c\x06\xd1G\x0bw\x84\xaa\xee\x8a?\xcbQ\x8e\x15q\xb7Ey\x8c4\xc3\xb2V\xe5\xc4$\xaf\x05?V\x86\x87\xae\xa2\x96\xa4x\xb2)4\xa5\xe3\x02RZ\xd6_\x8f\xe7U\xe8\x89\xca\x1f\xdd)\x81\x80\xba\xa0\x0c(\xfa\x85\x8a\xac\xa3\x8fH\xb5\xc2\xb8\xd1\x87\x0f\x89[\xa1\x94,\xe4\x05\xc6`\x94W\xc2iS\x01\xa9\xef\xc4=\x92!\rx,\xfeXe\xbb\xb7\n9j \xc4\xaeK\xf0W\xee\nY\xa0q\xd1\xbf\xb99\xc7\x12<\xaa\xca\xfb\xce\x0fCH\xdd\xa7\xb5\r%\xf3\x88\xa7\xd4\xda\xdck\xbe\x186\t\x82\xe8\x99t\xd1\x83\xff\x94+\xa5\xd9\xc0\x8e\xbf\x0c\xf3\xaf\xce\x06K\x86M.\xb8\xaa\x0c\xa5\x0c\xc38\xa8`\x0e\xd9Xq\x10\x007\x99\x81\x9d\xb8O\xeft\xac7\xbcWSN\xaf\xae\x87x\xfb\x82\x18`x\x99\x98\x16\x01AB^\xde\xdf\xa9\xbd{\x93\xdc\xc4\xb8\x9fN\xd5\x8a \x15I\x0c\xcf\n.n\xde\xcbgY\x1b\x1b\xb8$\xb0\xb0\xe4\x13\x1a\x8eN9\xf4Ri\xe3\xdc\x95\xc0\xc8\xc0\xb3\x96\xe2r\x99\xa1\xe9\xfd\xc4\x9e\xfaC\xd3b\x17kT5}\xb1\xbf\xa9\xb3\x03\x186s\xe2\xc7\xc2\xd9\xb25k}\x9fU8\xf9\xa1a\xa0\x994\x029)!\x97\xdf\x87\xda\xcb\x87uO\xfaWTi:\x97$\xfe\xbe/\xb4{\x12\xc3\xa7\n\xe99\x9a,\x08j\x05f\x0f\xd38\xa5\xd9\xc8\x83*k\xc5D\xe3{\x01\xab2\x96\x8c#*\x14|<\xbbFQ\x04\x12\xb6\x1b\xb6\xe3\xf0\xad#\xebg\xf8\xb9\x95\xc1\x98U\xe3u\xa7\x1a|:\xb8\x9d\xa7\x12\xdf\xfc\xa0\x1a\xbb\\\xc8i\x95Zg\xe3Z\xfc\x14?\x17nT\n\x80\xa9Q\xe8A \xfdX\x121E\xd3P\xf4FguK!\x94U\xc6\xda\xed\xd5\x0f\x87\xb9\x7f3\xc3\xd1\x0b\x83c2r6\xed\xa1*\xf8n\x88B\xc4\x94\xbb\x00d\xc1r%6S\xbbq\x02hx\xc1z_p\xd0\x8d\x15\x94\xc0\x90\xa7\x81O\x870ID\xc8\x96\xed\x9cn\xd4\x9d*\x81s\xd3\x89\x8c2<\xad\xac\x0b\x99z\xd8%\x94w\xb0!$N\xe6Gl\xb1k\x87\xf9v\x95e-\x05\x03U$\x1fk\xaf\xc2k\x17\xac_\x0ct\x06\xab\xdd\x040\xc8\xd6O\xd1\xe8\xa2\xf4\xb1\xe0G\x19\x00\x13\x83\x87\xeb\xc7\xd9\xablW\xda\x00\xd4\x9dMmf\xc7Q\xb5\xcf\x1f\x91\x04\x160\xcc\xce{\xd2iw\xed\xcc\x07m\xebc+\x99\x16\x14\x1e\r\x1d\xda,\x98\x16\xdf\xdc\xd4\x92\xd3\xccj5\x80\xf1\xcc\x0f\xf1\xf7C\xe6\x82\xc6\xf5j-\x16\xcc\xfb(#\xe0\'\xb5\xc1\x83\x88\x17\xb2\x9e$\xbd\xa6\x17;\xbd\xf8\xfb\x96\xc4w\x93.QE\xb1E\x97:\x08x\xa04kK\\\xdf\xfe@\x04\x8a\xe9\xfb\xccl\xd6V(\x89\x7f\xde*\xc3\xd9\x92\x8f"\x03\x1b\xea"\xab\x99\x18[G\xc3\x06\x02\xbc\xbbB\xb4,\x05a\x97\x86\x9bw\x91[H\xach#\x01b\x7f\xa5\x7f\xf0{o\x047\x91\x13\xf4\xeb<.,\x9a\xe6\x1f\xb1_\xaf\xd4\x8a\xdbw\xcc\n\xa7|\xc4F\x02\xa5\x8f\x81\xef\x929\xb0\x8c\xea\xfaLw0!\xe8m\xa0L\ne\xfa \xd1\x7f\xcei\x11\x1fc\xfbp\xcbB\xe1\xb5\t\xb2\x02\x83g\xe8` 4zY\xc0zz\xc1\x8d\x83\x0e\x90:r\xafl\x9f\xa5\x95\x1b\x1d-\x98R\xdf\xcfU*\xad\x13\xd28\xa5f\xbci\xa0\xa37}\rpc\x17IC\xa1\r\xda\xae\xd1\x02\xfc\x0fn\x7f&\xd8L\x16\xab\xb8jd\x03i\xf42i\xcd\x17\x85\xf9\xce\xd2\xbe\xae\x9cY\xd8P\xf1\x93\x1c\x06\xc62a\xc2T\x85\x88\xf3w\xfd\xa3\x8d\x82\x94c\xb4\xcaLG\xe5\xb1\x02\xa4S\xbb\xdfC\xe7r\xd7\xe1\xd0\x18\x06\xcecc\x8a\x96\xaf\x1f\xea\xcd\x9bt!\xeaRz\xde\xba\x98\xa7\xae\x01\x9a\xd5\x94\xf7\x07oFI\xe8\x08\xeb\xa7Jm\xf0\xc6\xfd\x9ed\xfb\xdbG\n"\xb5\x93\xf3\\\xa4\xf7\xee^\x8c\xbd\x15\x06e\xda\xbe\xf5\xa1p\x18\x1b6\x914e{\xe2 \xa9\xa2K\x9e\xbc\x7f\xae\\\xceX\xc6_\x0b0s\xb6\xd4\x92\xd9\x85\xfedS\xd4\x03\xafk^FiZ\xeces\xcd\x98\xe1\x11\x9c$\xe1\xcd\x81}\x91\xf9\xd3\x86\x9e\xa78\x00\xa0\x98!\xd7J\x1d\x86\xf4N\x964\x8e\x9f%=\x95\xa3\xd8\xb7z\xfd\xb0\xa5\xc81s\xa1\x9134\x88\xaa\xfb\xb8V*\xe3\xd6\xa7\x9c\x98KK\xdcm\xc5)\xa4\xc0\xc8\x11\xcd\x1e\x19k\x9e\x82\t\x90H\xaf\xde\x08\xbd\xbd\xc0_\x9b\xb2"\x1a\xbd\xd7\x0f\x9d\x1c4\xfa\xa2\xfc\x96\xe0G\xa7\x1a\xc1)\xba=\xcc;_\x84\xcf$\'\x1c9=\xb3\x99\xd1\x061{U\xb8\x1bF5\x9bw!\xec\x8f1\x9c\x8f\xa8\x97\xe9\x08\xc3\x86\xb4\xf0\x98,\xf1\xef\x96R:\xc5\x9c\x91u\xd4_\xc1xy\x1az\xc8\x9a\x10@z\xfe\xaf(c^\xf6\x10B\xc6\xc5-y\x8c\xb2T.\xfe%\x7f\x12iG\xd9q\x97\xf5\xa9\xc8\x0c\x9a(\x1f\xde\xfb\xd9\xdcy\xd8np\xfdt \xd5\xc9Q\xcf\xc3-W\xa9\xeee\xaa\xc3\x17\xd6!\xba\xfaCS\xd2\x84\x86\x0c\xd5QHd@vG\x1d\xd5\xef$q\x85\xfc\xf7\xcb\xca\xe5>V9"PO\xaf]:\xe2\xe4\t;h\xcc\xfe\xd5\x0c\x9d\xbb\xd2\x16\xa1\xa5\x82\x8d{\xac\xefz\xe2\x88\xb6\x19\x8f$\x1eSz\x8c\xe9\xd3b\xc8\x9e\xd15`\x8e\xc3#\xabp\x838\xfc\xf4o\xff.a\xdf\x07\xa8\xa4\xbe\xd3\xd7\x97>=\xc9\xad\xe6\xcbG\t4\xc7\x1f\xd9|\xbc\xe5\xb0\xe2M\x9e*\xfa\xff@0\xe5\xfe\xffU8&\xc5\x0e\x16\xbdS\xc5$\xa7\xe0Z\x89\xaf;\x07\xa2\xf7\xcdB!\x8c\x934\xcf\xf3ez3\x1a\x8b\xe4WT\x9d\x1e\xcc8\xbe\xac\xf2YNJ\x05\x9cd\xdcn\x87J\x93\x94\xe6\x04d\xbd\xec\xa8\xc5\xca\x8a\xbe4\xf4\x0b\xc1\x199Y\xd7\xbdK\xb2\xa3\xe7\xb7\x0e\x03\xdc\x02\x03\x87]\xc1\xb7\x8f\xd9\x1d\xfe\xa1\xda\x1d\x9c\x88`\x14\xba\xcd\xa78\xfb6E\xe2\xabG\x17A,>\x89,\xa8y\xb2\x91\x17\xefcM\xe8x\xb5\xec\xfe2\xca\xcc\xe3\xd3\x7f\xd7\x93"\xd2l\xad\xd7\xc2\xf6.3\x7fJ|\x99\xe5\xabPXMK8\x00Q\xf0\x9a9~\xb6\xfe\x86\xeca"0x\xe3\x86\xe0\xe7\xa4u^\xf3\t\\\xc5^W\xe0\x08\xda:P\x10\xe3\xefc\xcf\x14E\xff\x94\xd4\x08\x0e\xd2\xa7\xe3I[\x99\xfc\\[__\xc1\x84,NB\xf5b?\xec\x01le8\x1a\xd5\xd4X\xa4\xc5\xea\xf2\xb8\xf3\xbe\xd6\xa2\'9x{\xb3\xf6I(<\x0c\xb4\x1a\x10\x14x\xd4\xb1q^\xffm\x12\x88\xea\xfe\xde\xf4\xd4\xd2\xc2Q#\xd23[\xc45\x8a\xa1n9\x8c1\x16vJ\x1b\xcb\x91D\xfdd\xbb\xa6\xcb\nV\xebU\x8d\xea\x94\x91\xf7\x9d\xe6\x9f\x13\xc1\xb8\x1e\xbc\x1e\x8e+;\x87\x9a\xd82\xf8\xc4\xadi\x08\xf9\x10\xd3\x9c\x89\x03\xa8\x96\xff-\x85\x81\xf4e/r`cT_\x97\xb6F\xb5\xb7|\xe0\x16a6/AK\x81\xfe${\xab\t4\xcd\xa0@\x0e\xb1\xb1\x05\xa2\x88\x14"\xe3\xccEb\xd24\xc5\x9f\xeb6\xf4&l\xbf\x9e\xc1r\xf8j#\xa7\x87\xcf\xd2\n\x997\xe5\rhG\xacMRG\x00S\x15hC\x12\x9f\x9b\xf8\xd9\xf9_x\xaa\xb5A\xb9\x84\n:\xc8*o\xff\x0b\xf0\xee\xb4\xe8\xe4B\xcb\xbb\xdbF1\xd0:\xaa\x13\xb9\x9d\x98\x85\xe5\x8bl\xa3\xb6\xd1\x97m\x81\x17\xf0ce\x81@%1\xcc\xefqV\x81\xa6\x81\xcaC\xbb\xdcy\xaea\x0e\x99\x14\xc2\x8f\xd8nT\xc0q\xcf\x98S\x0e\x0bd\x87n\x88\xf8\xa1\xc0\xb60X5\xec`\x04\x01\xc8s$\xb4\xb0F\xad\xc7K\xfb\xec\xc3\r\x86D2\x07\xd1\xc9\x94\xa7\xe4N\xd4\xd7\x14\xfc\x9f{\xd1=\x94V\xc2|\xedb\xfd\x91\x87\x08\xa2kD\xe5\x8c(\xad\xf7E\x15\xd3v\xaa)\'\r\xc2r\x93\xf0Z\xb8\xbe\xbb\xd4\x0e\xa7\x11\x13\xfc\xaaG\xd2M\x05\x93\x1b\xbd:\x01\x0eS13<#\x83\x8ae\x1e\x82f<\x0feg \xae:Z\xf8M\x8f\xa9|\xa0&\xbd\x1f\xe38O\xbe=\xcf\x9fPB\x95\x1cv\x1a\x9aA\x08\xd9\xba\xb9\xd6\xf6eA"\xd4\xdf\xbdN\xfdX\xd5\x1b\x07\x141\xe5\xa8\xbf\x88"\xcfp[r\x9d\xc2m\x87\x0fo\x1bl\xef\xd7\xd1\xc0\xeeH\xb4\xa2\xca\xc9{\xb8\xe8\xa2]95\x89\xfa\xebx\xceQ\xb1\xba\xe6\xa4' # noqa: E501 chest_file = self.location / chest_id @@ -121,18 +104,18 @@ def _getRawFromFile(self, chest_id) -> bytes: return xor(data, key) def parse_from_log(self, _=None) -> dict[str, QuarEntry]: - logging.info("Parsing from log in %s", self.name) + logger.info("Parsing from log in %s", self.name) if not self._initDB(): return {} quarfiles = {} # Return the value of a field 'f' - @log_fn + @log.log(lgr=logger) def get(e: ET, f) -> str: return e.find(f).text for idx, e in enumerate(self.root.findall("ChestEntry")): - logging.debug("Parsing entry, idx %s", idx) + logger.debug("Parsing entry, idx %s", idx) chest_id = get(e, "ChestId") path = get(e, "OrigFolder") + "\\" + get(e, "OrigFileName") # Check if an entry is in the vault.db @@ -155,31 +138,31 @@ def get(e: ET, f) -> str: def parse_from_fs( self, data: dict[str, QuarEntry] | None = None ) -> dict[str, QuarEntry]: - logging.info("Parsing from filesystem in %s", self.name) + logger.info("Parsing from filesystem in %s", self.name) quarfiles = {} # iterating over bigger files, which were not logged to vault.db for idx, entry in enumerate(self.location.glob("*")): - logging.debug('Parsing entry, idx %s, path "%s"', idx, entry) + logger.debug('Parsing entry, idx %s, path "%s"', idx, entry) chest_id = entry.name if not entry.is_file(): - logging.debug("Entry (idx %s) is not a file, skipping", idx) + logger.debug("Entry (idx %s) is not a file, skipping", idx) continue if chest_id == "index.xml": - logging.debug("Entry (idx %s) is index.xml itself, skipping", idx) + logger.debug("Entry (idx %s) is index.xml itself, skipping", idx) continue if chest_id in data: - logging.debug("Entry (idx %s) already found, skipping", idx) + logger.debug("Entry (idx %s) already found, skipping", idx) continue malfile = self._getRawFromFile(chest_id) entry_stat = parse(self).entry_stat(entry) if entry_stat is None: - logging.debug('Skipping entry idx %s, path "%s"', idx, entry) + logger.debug('Skipping entry idx %s, path "%s"', idx, entry) continue timestamp = DTC.get_dt_from_stat(entry_stat) size = entry_stat.st_size diff --git a/maldump/parsers/avira_parser.py b/maldump/parsers/avira_parser.py index 256c567..122945b 100755 --- a/maldump/parsers/avira_parser.py +++ b/maldump/parsers/avira_parser.py @@ -6,20 +6,22 @@ from maldump.structures import Parser, QuarEntry from maldump.utils import Parser as parse +logger = logging.getLogger(__name__) + class AviraParser(Parser): def parse_from_log(self, data=None): pass def parse_from_fs(self, _=None) -> dict[str, QuarEntry]: - logging.info("Parsing from filesystem in %s", self.name) + logger.info("Parsing from filesystem in %s", self.name) quarfiles = {} for idx, metafile in enumerate(self.location.glob("*.qua")): - logging.debug('Parsing entry, idx %s, path "%s"', idx, metafile) + logger.debug('Parsing entry, idx %s, path "%s"', idx, metafile) kt = parse(self).kaitai(KaitaiParser, metafile) if kt is None: - logging.debug('Skipping entry idx %s, path "%s"', idx, metafile) + logger.debug('Skipping entry idx %s, path "%s"', idx, metafile) continue q = QuarEntry() diff --git a/maldump/parsers/eset_parser.py b/maldump/parsers/eset_parser.py index 1d18d19..7850b03 100644 --- a/maldump/parsers/eset_parser.py +++ b/maldump/parsers/eset_parser.py @@ -25,14 +25,14 @@ from maldump.parsers.kaitai.eset_virlog_parser import EsetVirlogParser from maldump.structures import Parser, QuarEntry from maldump.utils import DatetimeConverter as DTC +from maldump.utils import Logger as log from maldump.utils import Parser as parse from maldump.utils import Reader as read if typing.TYPE_CHECKING: from datetime import datetime -if typing.TYPE_CHECKING: - from datetime import datetime +logger = logging.getLogger(__name__) __author__ = "Ladislav Baco" __copyright__ = "Copyright (C) 2017" @@ -43,27 +43,7 @@ __status__ = "Development" -def log_fn(func): - def wrapper(*args, **kwargs): - logging.debug( - "Calling function: %s, arguments: %s, keyword arguments: %s", - func.__name__, - tuple( - ( - arg - if type(arg) not in {bytes, EsetParser} - else "<" + type(arg).__name__ + ">" - ) - for arg in args - ), - kwargs, - ) - return func(*args, **kwargs) - - return wrapper - - -@log_fn +@log.log(lgr=logger) def parseRecord(record: dict): return { "timestamp": record.get("timestamp"), @@ -78,7 +58,7 @@ def parseRecord(record: dict): } -@log_fn +@log.log(lgr=logger) def convertToDict(parser: EsetVirlogParser): return [ { @@ -92,11 +72,11 @@ def convertToDict(parser: EsetVirlogParser): ] -@log_fn +@log.log(lgr=logger) def mainParsing(virlog_path): kt = parse(EsetParser).kaitai(EsetVirlogParser, virlog_path) if kt is None: - logging.warning("Skipping virlog.dat parsing") + logger.warning("Skipping virlog.dat parsing") return [] kt.close() @@ -104,7 +84,7 @@ def mainParsing(virlog_path): parsedRecords = [] for idx, record in enumerate(threats): - logging.debug("Parsing raw record %s/%s", idx + 1, len(threats)) + logger.debug("Parsing raw record %s/%s", idx + 1, len(threats)) parsedRecords.append(parseRecord(record)) return [parseRecord(record) for record in threats] @@ -119,11 +99,11 @@ def __init__(self): ) self.regex_entry = re.compile(r"([0-9a-fA-F]+)\.NQF$") - @log_fn + @log.log(lgr=logger) def _decrypt(self, data: bytes) -> bytes: return bytes([((b - 84) % 256) ^ 0xA5 for b in data]) - @log_fn + @log.log(lgr=logger) def _get_malfile(self, username: str, sha1: str) -> bytes: quarfile = self.quarpath.format(username=username) quarfile = Path(quarfile) / (sha1.upper() + ".NQF") @@ -134,12 +114,12 @@ def _get_malfile(self, username: str, sha1: str) -> bytes: return self._decrypt(data) - @log_fn + @log.log(lgr=logger) def _get_metadata(self, path: Path, objhash: str) -> KaitaiParserMetadata | None: # metadata file has .NDF extension metadata_path = path / (objhash + ".NDF") if not metadata_path.is_file(): - logging.debug("Metadata file not found") + logger.debug("Metadata file not found") return None kt = parse(self).kaitai(KaitaiParserMetadata, metadata_path) @@ -150,13 +130,13 @@ def _get_metadata(self, path: Path, objhash: str) -> KaitaiParserMetadata | None return kt def parse_from_log(self, _=None) -> dict[tuple[str, datetime], QuarEntry]: - logging.info("Parsing from log in %s", self.name) + logger.info("Parsing from log in %s", self.name) quarfiles: dict[tuple[str, datetime], QuarEntry] = {} for idx, metadata in enumerate(mainParsing(self.location)): - logging.debug("Parsing entry, idx %s", idx) + logger.debug("Parsing entry, idx %s", idx) if metadata["user"] == "SYSTEM": - logging.debug("Entry's (idx %s) user is SYSTEM, skipping", idx) + logger.debug("Entry's (idx %s) user is SYSTEM, skipping", idx) continue q = QuarEntry() q.timestamp = metadata["timestamp"] @@ -170,19 +150,19 @@ def parse_from_log(self, _=None) -> dict[tuple[str, datetime], QuarEntry]: def parse_from_fs( self, data: dict[tuple[str, datetime], QuarEntry] | None = None ) -> dict[tuple[str, datetime], QuarEntry]: - logging.info("Parsing from filesystem in %s", self.name) + logger.info("Parsing from filesystem in %s", self.name) quarfiles = {} actual_path = Path("Users/") for idx, entry in enumerate( actual_path.glob("*/AppData/Local/ESET/ESET Security/Quarantine/*.NQF") ): - logging.debug('Parsing entry, idx %s, path "%s"', idx, entry) + logger.debug('Parsing entry, idx %s, path "%s"', idx, entry) res_path = re.match(self.regex_entry, entry.name) res_user = re.match(self.regex_user, str(entry)) if not res_path: - logging.debug( + logger.debug( "Entry's (idx %s) filename of incorrect format, skipping", idx ) continue @@ -191,12 +171,12 @@ def parse_from_fs( objhash = res_path.group(1) if (objhash.lower(), user) in data: - logging.debug("Entry (idx %s) already found, skipping", idx) + logger.debug("Entry (idx %s) already found, skipping", idx) continue entry_stat = parse(self).entry_stat(entry) if entry_stat is None: - logging.debug('Skipping entry idx %s, path "%s"', idx, entry) + logger.debug('Skipping entry idx %s, path "%s"', idx, entry) continue timestamp = DTC.get_dt_from_stat(entry_stat) path = str(entry) diff --git a/maldump/parsers/forticlient_parser.py b/maldump/parsers/forticlient_parser.py index 3a818e1..de6c8d3 100755 --- a/maldump/parsers/forticlient_parser.py +++ b/maldump/parsers/forticlient_parser.py @@ -5,38 +5,20 @@ from maldump.parsers.kaitai.forticlient_parser import ForticlientParser as KaitaiParser from maldump.structures import Parser, QuarEntry +from maldump.utils import Logger as log from maldump.utils import Parser as parse - -def log_fn(func): - def wrapper(*args, **kwargs): - logging.debug( - "Calling function: %s, arguments: %s, keyword arguments: %s", - func.__name__, - tuple( - ( - arg - if type(arg) - not in {bytes, ForticlientParser, KaitaiParser.Timestamp} - else "<" + type(arg).__name__ + ">" - ) - for arg in args - ), - kwargs, - ) - return func(*args, **kwargs) - - return wrapper +logger = logging.getLogger(__name__) class ForticlientParser(Parser): - @log_fn + @log.log(lgr=logger) def _normalize_path(self, path): if path[2:4] == "?\\": path = path[4:] return path - @log_fn + @log.log(lgr=logger) def _get_time(self, ts): return dt(ts.year, ts.month, ts.day, ts.hour, ts.minute, ts.second) @@ -44,15 +26,15 @@ def parse_from_log(self, data=None): pass def parse_from_fs(self, _=None) -> dict[str, QuarEntry]: - logging.info("Parsing from log in %s", self.name) + logger.info("Parsing from log in %s", self.name) quarfiles = {} for idx, metafile in enumerate(self.location.glob("*[!.meta]")): - logging.debug('Parsing entry, idx %s, path "%s"', idx, metafile) + logger.debug('Parsing entry, idx %s, path "%s"', idx, metafile) kt = parse(self).kaitai(KaitaiParser, metafile) if kt is None: - logging.debug('Skipping entry idx %s, path "%s"', idx, metafile) + logger.debug('Skipping entry idx %s, path "%s"', idx, metafile) continue q = QuarEntry() diff --git a/maldump/parsers/gdata_parser.py b/maldump/parsers/gdata_parser.py index 682ca02..75f724a 100755 --- a/maldump/parsers/gdata_parser.py +++ b/maldump/parsers/gdata_parser.py @@ -6,21 +6,23 @@ from maldump.structures import Parser, QuarEntry from maldump.utils import Parser as parse +logger = logging.getLogger(__name__) + class GdataParser(Parser): def parse_from_log(self, data=None): pass def parse_from_fs(self, _=None) -> dict[str, QuarEntry]: - logging.info("Parsing from filesystem in %s", self.name) + logger.info("Parsing from filesystem in %s", self.name) quarfiles = {} for idx, metafile in enumerate(self.location.glob("*.q")): - logging.debug('Parsing entry, idx %s, path "%s"', idx, metafile) + logger.debug('Parsing entry, idx %s, path "%s"', idx, metafile) kt = parse(self).kaitai(KaitaiParser, metafile) if kt is None: - logging.debug('Skipping entry idx %s, path "%s"', idx, metafile) + logger.debug('Skipping entry idx %s, path "%s"', idx, metafile) continue q = QuarEntry() diff --git a/maldump/parsers/kaspersky_parser.py b/maldump/parsers/kaspersky_parser.py index 17c1f69..59baa2a 100644 --- a/maldump/parsers/kaspersky_parser.py +++ b/maldump/parsers/kaspersky_parser.py @@ -7,33 +7,16 @@ from maldump.constants import ThreatMetadata from maldump.structures import Parser, QuarEntry from maldump.utils import DatetimeConverter as DTC +from maldump.utils import Logger as log from maldump.utils import Parser as parse from maldump.utils import Reader as read from maldump.utils import xor - -def log_fn(func): - def wrapper(*args, **kwargs): - logging.debug( - "Calling function: %s, arguments: %s, keyword arguments: %s", - func.__name__, - tuple( - ( - arg - if type(arg) not in {bytes, KasperskyParser} - else "<" + type(arg).__name__ + ">" - ) - for arg in args - ), - kwargs, - ) - return func(*args, **kwargs) - - return wrapper +logger = logging.getLogger(__name__) class KasperskyParser(Parser): - @log_fn + @log.log(lgr=logger) def _normalize_time(self, number: int) -> datetime: year = (number >> 48) & 0xFFFF month = (number >> 40) & 0xFF @@ -44,7 +27,7 @@ def _normalize_time(self, number: int) -> datetime: return datetime(year, month, days, hours, minutes, seconds) - @log_fn + @log.log(lgr=logger) def _get_malfile(self, data) -> bytes: file = self.location / data key = bytes([0xE2, 0x45, 0x48, 0xEC, 0x69, 0x0E, 0x5C, 0xAC]) @@ -56,24 +39,24 @@ def _get_malfile(self, data) -> bytes: return xor(data, key) def parse_from_log(self, _=None) -> dict[str, QuarEntry]: - logging.info("Parsing from log in %s", self.name) + logger.info("Parsing from log in %s", self.name) quarfiles = {} db_file = self.location.joinpath("quarantine.db").resolve() try: - logging.debug( + logger.debug( 'Trying to open and read from database file, path "%s"', db_file ) conn = sqlite3.connect(db_file) - logging.debug('Opening cursor to a database connection, path "%s"', db_file) + logger.debug('Opening cursor to a database connection, path "%s"', db_file) cursor = conn.cursor() - logging.debug( + logger.debug( 'Exectuting a command with a database connection, path "%s"', db_file ) cursor.execute("SELECT * FROM 'objects'") rows = cursor.fetchall() except sqlite3.Error as e: - logging.exception( + logger.exception( 'Cannot open nor read from a database file, path "%s"', db_file, exc_info=e, @@ -98,26 +81,26 @@ def parse_from_log(self, _=None) -> dict[str, QuarEntry]: def parse_from_fs( self, data: dict[str, QuarEntry] | None = None ) -> dict[str, QuarEntry]: - logging.info("Parsing from filesystem in %s", self.name) + logger.info("Parsing from filesystem in %s", self.name) quarfiles = {} for idx, entry in enumerate(self.location.glob("{*}")): - logging.debug('Parsing entry, idx %s, path "%s"', idx, entry) + logger.debug('Parsing entry, idx %s, path "%s"', idx, entry) if not entry.is_file(): - logging.debug("Entry (idx %s) is not a file, skipping", idx) + logger.debug("Entry (idx %s) is not a file, skipping", idx) continue filename = entry.name if filename in data: - logging.debug("Entry (idx %s) already found, skipping", idx) + logger.debug("Entry (idx %s) already found, skipping", idx) continue malfile = self._get_malfile(filename) entry_stat = parse(self).entry_stat(entry) if entry_stat is None: - logging.debug('Skipping entry idx %s, path "%s"', idx, entry) + logger.debug('Skipping entry idx %s, path "%s"', idx, entry) continue timestamp = DTC.get_dt_from_stat(entry_stat) size = entry_stat.st_size diff --git a/maldump/parsers/malwarebytes_parser.py b/maldump/parsers/malwarebytes_parser.py index 135be02..49d557b 100644 --- a/maldump/parsers/malwarebytes_parser.py +++ b/maldump/parsers/malwarebytes_parser.py @@ -8,32 +8,15 @@ from maldump.structures import Parser, QuarEntry from maldump.utils import CustomArc4 from maldump.utils import DatetimeConverter as DTC +from maldump.utils import Logger as log from maldump.utils import Parser as parse from maldump.utils import Reader as read - -def log_fn(func): - def wrapper(*args, **kwargs): - logging.debug( - "Calling function: %s, arguments: %s, keyword arguments: %s", - func.__name__, - tuple( - ( - arg - if type(arg) not in {bytes, MalwarebytesParser} - else "<" + type(arg).__name__ + ">" - ) - for arg in args - ), - kwargs, - ) - return func(*args, **kwargs) - - return wrapper +logger = logging.getLogger(__name__) class MalwarebytesParser(Parser): - @log_fn + @log.log(lgr=logger) def _decrypt(self, plaintext: bytes) -> bytes: key = bytes( [ @@ -57,19 +40,19 @@ def _decrypt(self, plaintext: bytes) -> bytes: ) return CustomArc4(key).decode(plaintext) - @log_fn + @log.log(lgr=logger) def _normalize_time(self, date: str) -> datetime: return datetime.strptime(date, "%Y-%m-%dT%H:%M:%SZ") def parse_from_log(self, _=None) -> dict[str, QuarEntry]: - logging.info("Parsing from log in %s", self.name) + logger.info("Parsing from log in %s", self.name) quarfiles = {} for idx, metafile in enumerate(self.location.glob("*.data")): - logging.debug('Parsing entry, idx %s, path "%s"', idx, metafile) + logger.debug('Parsing entry, idx %s, path "%s"', idx, metafile) metadata = read.contents(metafile) if metadata is None: - logging.debug('Skipping entry idx %s, path "%s"', idx, metafile) + logger.debug('Skipping entry idx %s, path "%s"', idx, metafile) continue decrypted = self._decrypt(metadata) @@ -94,23 +77,23 @@ def parse_from_log(self, _=None) -> dict[str, QuarEntry]: def parse_from_fs( self, data: dict[str, QuarEntry] | None = None ) -> dict[str, QuarEntry]: - logging.info("Parsing from filesystem in %s", self.name) + logger.info("Parsing from filesystem in %s", self.name) quarfiles = {} for idx, entry in enumerate(self.location.glob("*.quar")): - logging.debug('Parsing entry, idx %s, path "%s"', idx, entry) + logger.debug('Parsing entry, idx %s, path "%s"', idx, entry) if not entry.is_file(): - logging.debug("Entry (idx %s) is not a file, skipping", idx) + logger.debug("Entry (idx %s) is not a file, skipping", idx) continue uid = entry.name.rstrip(".quar") if uid in data: - logging.debug("Entry (idx %s) already found, skipping", idx) + logger.debug("Entry (idx %s) already found, skipping", idx) continue entry_stat = parse(self).entry_stat(entry) if entry_stat is None: - logging.debug('Skipping entry idx %s, path "%s"', idx, entry) + logger.debug('Skipping entry idx %s, path "%s"', idx, entry) continue timestamp = DTC.get_dt_from_stat(entry_stat) size = entry_stat.st_size diff --git a/maldump/parsers/mcafee_parser.py b/maldump/parsers/mcafee_parser.py index 5d59603..9ef4b97 100644 --- a/maldump/parsers/mcafee_parser.py +++ b/maldump/parsers/mcafee_parser.py @@ -10,6 +10,9 @@ import defusedxml.ElementTree as ET from maldump.structures import Parser, QuarEntry +from maldump.utils import Logger as log + +logger = logging.getLogger(__name__) class McafeeFileData(TypedDict): @@ -20,26 +23,6 @@ class McafeeFileData(TypedDict): mal_file: bytes -def log_fn(func): - def wrapper(*args, **kwargs): - logging.debug( - "Calling function: %s, arguments: %s, keyword arguments: %s", - func.__name__, - tuple( - ( - arg - if type(arg) not in {bytes, McafeeParser} - else "<" + type(arg).__name__ + ">" - ) - for arg in args - ), - kwargs, - ) - return func(*args, **kwargs) - - return wrapper - - class McafeeParser(Parser): """XML parser""" @@ -55,14 +38,14 @@ def parse_from_log(self, data=None): def parse_from_fs( self, _: dict[str, QuarEntry] | None = None ) -> dict[str, QuarEntry]: - logging.info("Parsing from filesystem in %s", self.name) + logger.info("Parsing from filesystem in %s", self.name) quarfiles = {} for idx, metafile in enumerate(self.location.glob("*.zip")): - logging.debug('Parsing entry, idx %s, path "%s"', idx, metafile) + logger.debug('Parsing entry, idx %s, path "%s"', idx, metafile) parser = self._get_data(file_name=metafile) if parser is None: - logging.debug('Skipping entry idx %s, path "%s"', idx, metafile) + logger.debug('Skipping entry idx %s, path "%s"', idx, metafile) q = QuarEntry() q.timestamp = dt.strptime(parser["timestamp"], "%Y-%m-%d %H:%M:%S") @@ -74,26 +57,24 @@ def parse_from_fs( return quarfiles - @log_fn + @log.log(lgr=logger) def _get_data(self, file_name: str) -> McafeeFileData | None: # unzip file - logging.debug('Checking if file is a ZIP file, path "%s"', file_name) + logger.debug('Checking if file is a ZIP file, path "%s"', file_name) if not zipfile.is_zipfile(filename=file_name): - logging.warning( + logger.warning( 'File is not a ZIP file "%s" in class %s.', file_name, self.__name__ ) return None try: - logging.debug('Trying to open a ZIP file, path "%s"', file_name) + logger.debug('Trying to open a ZIP file, path "%s"', file_name) with ZipFile(file=file_name, mode="r") as archive: - logging.debug("Setting a passford for a ZIP file") + logger.debug("Setting a passford for a ZIP file") archive.setpassword(self._zip_password.encode()) for idx, file in enumerate(archive.namelist()): - logging.debug( - 'Traversing a ZIP file, idx %s, file: "%s"', idx, file - ) + logger.debug('Traversing a ZIP file, idx %s, file: "%s"', idx, file) # save files to private variables text = archive.read(file).decode(encoding="utf-8") if re.search(self._re_xml, text) and self._xml_data == "": @@ -103,19 +84,19 @@ def _get_data(self, file_name: str) -> McafeeFileData | None: return self._read() except RuntimeError as e: - logging.exception( + logger.exception( 'Cannot open a ZIP file on path "%s"', file_name, exc_info=e ) return None - @log_fn + @log.log(lgr=logger) def _read(self) -> McafeeFileData | None: try: - logging.debug("Trying to parse an XML file from data in McAfee") + logger.debug("Trying to parse an XML file from data in McAfee") root = ET.fromstring(self._xml_data) except ET.ParseError as e: - logging.exception("Cannot parse an XML file in McAfee", exc_info=e) + logger.exception("Cannot parse an XML file in McAfee", exc_info=e) return None parser = { diff --git a/maldump/parsers/windef_parser.py b/maldump/parsers/windef_parser.py index 58c2c3a..2304f2e 100644 --- a/maldump/parsers/windef_parser.py +++ b/maldump/parsers/windef_parser.py @@ -9,38 +9,21 @@ ) from maldump.structures import Parser, QuarEntry from maldump.utils import DatetimeConverter as DTC +from maldump.utils import Logger as log from maldump.utils import Parser as parse - -def log_fn(func): - def wrapper(*args, **kwargs): - logging.debug( - "Calling function: %s, arguments: %s, keyword arguments: %s", - func.__name__, - tuple( - ( - arg - if type(arg) not in {bytes, WindowsDefenderParser} - else "<" + type(arg).__name__ + ">" - ) - for arg in args - ), - kwargs, - ) - return func(*args, **kwargs) - - return wrapper +logger = logging.getLogger(__name__) class WindowsDefenderParser(Parser): - @log_fn + @log.log(lgr=logger) def _normalize(self, path_chrs) -> str: path_str = "".join(map(chr, path_chrs[:-1])) if path_str[2:4] == "?\\": path_str = path_str[4:] return path_str - @log_fn + @log.log(lgr=logger) def _get_metadata(self, guid: str): quarfile = self.location / "ResourceData" / guid[:2] / guid @@ -50,7 +33,7 @@ def _get_metadata(self, guid: str): return kt - @log_fn + @log.log(lgr=logger) def _get_malfile(self, guid: str) -> bytes: kt = self._get_metadata(guid) if kt is None: @@ -58,24 +41,24 @@ def _get_malfile(self, guid: str) -> bytes: return kt.encryptedfile.mal_file def parse_from_log(self, _=None) -> dict[str, QuarEntry]: - logging.info("Parsing from log in %s", self.name) + logger.info("Parsing from log in %s", self.name) quarfiles = {} for idx, metafile in enumerate(self.location.glob("Entries/{*}")): - logging.debug('Parsing entry, idx %s, path "%s"', idx, metafile) + logger.debug('Parsing entry, idx %s, path "%s"', idx, metafile) kt = parse(self).kaitai(KaitaiParserEntries, metafile) if kt is None: - logging.debug('Skipping entry idx %s, path "%s"', idx, metafile) + logger.debug('Skipping entry idx %s, path "%s"', idx, metafile) continue ts = parse(self).timestamp(kt.data1.time.unixts) # Loop through all entries, if they exist for idx_e, e in enumerate(kt.data2.entries): - logging.debug("Parsing entry inside metadata file, idx_e %s", idx_e) + logger.debug("Parsing entry inside metadata file, idx_e %s", idx_e) # Support only 'file' type for now if e.entry.typestr != "file": - logging.debug("Entry (idx_e %s) is not a file, skipping", idx_e) + logger.debug("Entry (idx_e %s) is not a file, skipping", idx_e) continue guid = e.entry.element[0].content.value.hex().upper() @@ -94,25 +77,25 @@ def parse_from_log(self, _=None) -> dict[str, QuarEntry]: def parse_from_fs( self, data: dict[str, QuarEntry] | None = None ) -> dict[str, QuarEntry]: - logging.info("Parsing from filesystem in %s", self.name) + logger.info("Parsing from filesystem in %s", self.name) quarfiles = {} # if the metadata are lost, but we still have access to data themselves for idx, entry in enumerate(self.location.glob("ResourceData/*/*")): - logging.debug('Parsing entry, idx %s, path "%s"', idx, entry) + logger.debug('Parsing entry, idx %s, path "%s"', idx, entry) if not entry.is_file(): - logging.debug("Entry (idx %s) is not a file, skipping", idx) + logger.debug("Entry (idx %s) is not a file, skipping", idx) continue guid = entry.name if guid in data: - logging.debug("Entry (idx %s) already found, skipping", idx) + logger.debug("Entry (idx %s) already found, skipping", idx) continue entry_stat = parse(self).entry_stat(entry) if entry_stat is None: - logging.debug('Skipping entry idx %s, path "%s"', idx, entry) + logger.debug('Skipping entry idx %s, path "%s"', idx, entry) continue timestamp = DTC.get_dt_from_stat(entry_stat) @@ -120,7 +103,7 @@ def parse_from_fs( kt_data = self._get_metadata(guid) if malfile is None: - logging.debug('Skipping entry idx %s, path "%s"', idx, entry) + logger.debug('Skipping entry idx %s, path "%s"', idx, entry) continue q = QuarEntry() From e17c9b534e3d72345b42eb9ef5850fd18e82f213 Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Tue, 22 Apr 2025 13:33:31 +0200 Subject: [PATCH 33/40] Use local logger in __main__.py --- maldump/__main__.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/maldump/__main__.py b/maldump/__main__.py index 30b7e5b..637c884 100755 --- a/maldump/__main__.py +++ b/maldump/__main__.py @@ -22,6 +22,7 @@ from maldump.structures import Quarantine __version__ = "0.5.0" +logger: logging.Logger | None = None def main() -> None: @@ -31,7 +32,7 @@ def main() -> None: # Admin privileges are required for optimal function (windows only) if sys.platform == "win32" and not ctypes.windll.shell32.IsUserAnAdmin(): - logging.critical( + logger.critical( "The program executed on Windows machine without proper privileges" ) print("Please try again with admin privileges") @@ -43,14 +44,14 @@ def main() -> None: # Switch to root partition os.chdir(args.root_dir) - logging.debug( + logger.debug( 'Working in directory "%s", files would be stored into "%s"', os.getcwd(), dest ) # Get a list of all installed avs avs = AVManager.detect() - logging.debug("Detected AVs: %s", [av.name for av in avs]) + logger.debug("Detected AVs: %s", [av.name for av in avs]) if args.quar: export_files(avs, dest) @@ -190,10 +191,10 @@ def parse_cli() -> argparse.Namespace: def init_logging(log_level: str) -> None: + global logger # noqa: PLW0603 numeric_level = getattr(logging, log_level.upper(), None) if not isinstance(numeric_level, int): raise ValueError("Invalid log level: " + log_level) # noqa: TRY004 - logging.basicConfig( handlers=[ # logging.FileHandler("syslog.log", mode="w", encoding="utf-8"), @@ -202,8 +203,9 @@ def init_logging(log_level: str) -> None: level=numeric_level, format="%(asctime)s:%(levelname)s:%(name)s:%(module)s:%(message)s", ) - logging.debug("Logging started, logger initialized successfully") - logging.info("Logging as user %s", getpass.getuser()) + logger = logging.getLogger(__name__) + logger.debug("Logging started, logger initialized successfully") + logger.info("Logging as user %s", getpass.getuser()) if __name__ == "__main__": From 60e891c923699dba6bd3e2ea9bc4c1d0e7a5677d Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Tue, 22 Apr 2025 13:34:52 +0200 Subject: [PATCH 34/40] Do not use global variable in __main__.py --- maldump/__main__.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/maldump/__main__.py b/maldump/__main__.py index 637c884..bc4bf66 100755 --- a/maldump/__main__.py +++ b/maldump/__main__.py @@ -22,7 +22,7 @@ from maldump.structures import Quarantine __version__ = "0.5.0" -logger: logging.Logger | None = None +logger = logging.getLogger(__name__) def main() -> None: @@ -190,8 +190,7 @@ def parse_cli() -> argparse.Namespace: return parser.parse_args() -def init_logging(log_level: str) -> None: - global logger # noqa: PLW0603 +def init_logging(log_level: str) -> None: # noqa: PLW0603 numeric_level = getattr(logging, log_level.upper(), None) if not isinstance(numeric_level, int): raise ValueError("Invalid log level: " + log_level) # noqa: TRY004 @@ -203,7 +202,6 @@ def init_logging(log_level: str) -> None: level=numeric_level, format="%(asctime)s:%(levelname)s:%(name)s:%(module)s:%(message)s", ) - logger = logging.getLogger(__name__) logger.debug("Logging started, logger initialized successfully") logger.info("Logging as user %s", getpass.getuser()) From 0b1738b28a06b4fdebc03060510c93ea7bb39f1a Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Tue, 22 Apr 2025 13:40:50 +0200 Subject: [PATCH 35/40] Fix types in utils.py --- maldump/utils.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/maldump/utils.py b/maldump/utils.py index 1b5122a..16a359a 100755 --- a/maldump/utils.py +++ b/maldump/utils.py @@ -7,7 +7,7 @@ import contextlib import logging from datetime import datetime, timezone -from typing import TYPE_CHECKING, Any, Generic, TypeVar, Callable +from typing import TYPE_CHECKING, Any, Callable, Generic, TypeVar from xml.etree.ElementTree import Element import kaitaistruct @@ -33,8 +33,8 @@ def xor(plaintext: bytes, key: bytes) -> bytes: class Logger: @staticmethod - def log(_func: Callable = None, *, lgr: logging.Logger = logger): - def log_fn(func: Callable) -> Any: + def log(_func: Callable | None = None, *, lgr: logging.Logger = logger): + def log_fn(func: Callable | None) -> Any: def wrapper(*args: tuple, **kwargs: dict) -> Any: lgr.debug( "Calling function: %s, arguments: %s, keyword arguments: %s", From cae9d7e642f82bdbf5dcb40b2da0253eb70df8a2 Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Tue, 22 Apr 2025 13:41:53 +0200 Subject: [PATCH 36/40] Fix types in utils.py 2 --- maldump/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maldump/__main__.py b/maldump/__main__.py index bc4bf66..228df84 100755 --- a/maldump/__main__.py +++ b/maldump/__main__.py @@ -190,7 +190,7 @@ def parse_cli() -> argparse.Namespace: return parser.parse_args() -def init_logging(log_level: str) -> None: # noqa: PLW0603 +def init_logging(log_level: str) -> None: numeric_level = getattr(logging, log_level.upper(), None) if not isinstance(numeric_level, int): raise ValueError("Invalid log level: " + log_level) # noqa: TRY004 From 568b60a39fc39ffd3da81eb0551a7f143fd93bb5 Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Tue, 22 Apr 2025 15:42:58 +0200 Subject: [PATCH 37/40] Fix imports in __init__.py --- maldump/parsers/__init__.py | 21 +++++++++++++++++++++ maldump/utils.py | 4 ++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/maldump/parsers/__init__.py b/maldump/parsers/__init__.py index e69de29..7455bdc 100644 --- a/maldump/parsers/__init__.py +++ b/maldump/parsers/__init__.py @@ -0,0 +1,21 @@ +from . import kaitai +from .avast_parser import AvastParser +from .avg_parser import AVGParser +from .eset_parser import EsetParser +from .forticlient_parser import ForticlientParser +from .kaspersky_parser import KasperskyParser +from .malwarebytes_parser import MalwarebytesParser +from .mcafee_parser import McafeeParser +from .windef_parser import WindowsDefenderParser + +__all__ = [ + "AVGParser", + "AvastParser", + "EsetParser", + "ForticlientParser", + "KasperskyParser", + "MalwarebytesParser", + "McafeeParser", + "WindowsDefenderParser", + "kaitai", +] diff --git a/maldump/utils.py b/maldump/utils.py index 16a359a..56af081 100755 --- a/maldump/utils.py +++ b/maldump/utils.py @@ -33,8 +33,8 @@ def xor(plaintext: bytes, key: bytes) -> bytes: class Logger: @staticmethod - def log(_func: Callable | None = None, *, lgr: logging.Logger = logger): - def log_fn(func: Callable | None) -> Any: + def log(_func: Callable | None = None, *, lgr: logging.Logger = logger) -> Any: + def log_fn(func: Callable) -> Any: def wrapper(*args: tuple, **kwargs: dict) -> Any: lgr.debug( "Calling function: %s, arguments: %s, keyword arguments: %s", From 4596952ce19e7a554d53e7ec0931400f36de4326 Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Wed, 23 Apr 2025 23:25:53 +0200 Subject: [PATCH 38/40] Fix logging for unlogged elements Unlogged types are now moved to separate class in constants.py --- maldump/constants.py | 24 ++++++++++++++++++++++++ maldump/utils.py | 19 ++----------------- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/maldump/constants.py b/maldump/constants.py index 731cd7e..1007f84 100644 --- a/maldump/constants.py +++ b/maldump/constants.py @@ -1,4 +1,8 @@ from enum import Enum +from typing import Any +from xml.etree.ElementTree import Element + +import maldump.parsers class OperatingSystem(Enum): @@ -9,3 +13,23 @@ class OperatingSystem(Enum): class ThreatMetadata(str, Enum): UNKNOWN_THREAT = "Unknown-no-metadata" + + +class UnloggedObjects(object): + _unlogged = { + bytes, + maldump.parsers.eset_parser.EsetParser, + maldump.parsers.avast_parser.AvastParser, + maldump.parsers.avg_parser.AVGParser, + maldump.parsers.forticlient_parser.ForticlientParser, + maldump.parsers.kaspersky_parser.KasperskyParser, + maldump.parsers.malwarebytes_parser.MalwarebytesParser, + maldump.parsers.mcafee_parser.McafeeParser, + maldump.parsers.windef_parser.WindowsDefenderParser, + maldump.parsers.kaitai.forticlient_parser.ForticlientParser.Timestamp, + Element, + } + + @classmethod + def __contains__(cls, item: Any) -> bool: + return item in cls._unlogged diff --git a/maldump/utils.py b/maldump/utils.py index 56af081..fac5bee 100755 --- a/maldump/utils.py +++ b/maldump/utils.py @@ -8,13 +8,11 @@ import logging from datetime import datetime, timezone from typing import TYPE_CHECKING, Any, Callable, Generic, TypeVar -from xml.etree.ElementTree import Element import kaitaistruct from arc4 import ARC4 -import maldump.parsers -from maldump.constants import OperatingSystem +from maldump.constants import OperatingSystem, UnloggedObjects if TYPE_CHECKING: from pathlib import Path @@ -42,20 +40,7 @@ def wrapper(*args: tuple, **kwargs: dict) -> Any: tuple( ( arg - if type(arg) - not in { - bytes, - maldump.parsers.eset_parser.EsetParser, - maldump.parsers.avast_parser.AvastParser, - maldump.parsers.avg_parser.AVGParser, - maldump.parsers.forticlient_parser.ForticlientParser, - maldump.parsers.kaspersky_parser.KasperskyParser, - maldump.parsers.malwarebytes_parser.MalwarebytesParser, - maldump.parsers.mcafee_parser.McafeeParser, - maldump.parsers.windef_parser.WindowsDefenderParser, - maldump.parsers.kaitai.forticlient_parser.ForticlientParser.Timestamp, - Element, - } + if type(arg) not in UnloggedObjects() else "<" + type(arg).__name__ + ">" ) for arg in args From 883479ed41e4500394019e2f5e8d217bed280b82 Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Wed, 23 Apr 2025 23:26:23 +0200 Subject: [PATCH 39/40] Fix spacing for the debugger --- maldump/utils.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/maldump/utils.py b/maldump/utils.py index fac5bee..bff035c 100755 --- a/maldump/utils.py +++ b/maldump/utils.py @@ -164,17 +164,14 @@ def entry_stat(self, entry: Any): # type: ignore class Reader: @staticmethod def contents(path: Path, filetype: str = "") -> bytes | None: - if filetype: - filetype += " " - try: - logger.debug('Trying to open %sfile, path "%s"', filetype, path) + logger.debug('Trying to open %s file, path "%s"', filetype, path) with open(path, "rb") as f: - logger.debug('Trying to read %sfile, path "%s"', filetype, path) + logger.debug('Trying to read %s file, path "%s"', filetype, path) data = f.read() except OSError as e: logger.exception( - 'Cannot open %sfile in ESET on path "%s"', filetype, path, exc_info=e + 'Cannot open %s file in ESET on path "%s"', filetype, path, exc_info=e ) data = None From 79ceb98a2e44f64b81071bdb8b80c5d564adcfd9 Mon Sep 17 00:00:00 2001 From: Jozef Sabo <31158086+jozef-sabo@users.noreply.github.com> Date: Thu, 24 Apr 2025 10:19:51 +0200 Subject: [PATCH 40/40] Move unlogged objects to a separate class alongside with their imports --- maldump/constants.py | 50 ++++++++++++++++++++++--------------- maldump/parsers/__init__.py | 21 ---------------- 2 files changed, 30 insertions(+), 41 deletions(-) diff --git a/maldump/constants.py b/maldump/constants.py index 1007f84..90e0cf0 100644 --- a/maldump/constants.py +++ b/maldump/constants.py @@ -2,8 +2,6 @@ from typing import Any from xml.etree.ElementTree import Element -import maldump.parsers - class OperatingSystem(Enum): WINDOWS = "windows" @@ -15,21 +13,33 @@ class ThreatMetadata(str, Enum): UNKNOWN_THREAT = "Unknown-no-metadata" -class UnloggedObjects(object): - _unlogged = { - bytes, - maldump.parsers.eset_parser.EsetParser, - maldump.parsers.avast_parser.AvastParser, - maldump.parsers.avg_parser.AVGParser, - maldump.parsers.forticlient_parser.ForticlientParser, - maldump.parsers.kaspersky_parser.KasperskyParser, - maldump.parsers.malwarebytes_parser.MalwarebytesParser, - maldump.parsers.mcafee_parser.McafeeParser, - maldump.parsers.windef_parser.WindowsDefenderParser, - maldump.parsers.kaitai.forticlient_parser.ForticlientParser.Timestamp, - Element, - } - - @classmethod - def __contains__(cls, item: Any) -> bool: - return item in cls._unlogged +class UnloggedObjects: + @staticmethod + def __contains__(item: Any) -> bool: + from maldump.parsers.avast_parser import AvastParser + from maldump.parsers.avg_parser import AVGParser + from maldump.parsers.eset_parser import EsetParser + from maldump.parsers.forticlient_parser import ForticlientParser + from maldump.parsers.kaitai.forticlient_parser import ( + ForticlientParser as ForticlientKaitaiParser, + ) + from maldump.parsers.kaspersky_parser import KasperskyParser + from maldump.parsers.malwarebytes_parser import MalwarebytesParser + from maldump.parsers.mcafee_parser import McafeeParser + from maldump.parsers.windef_parser import WindowsDefenderParser + + unlogged = { + bytes, + EsetParser, + AvastParser, + AVGParser, + ForticlientParser, + KasperskyParser, + MalwarebytesParser, + McafeeParser, + WindowsDefenderParser, + ForticlientKaitaiParser.Timestamp, + Element, + } + + return item in unlogged diff --git a/maldump/parsers/__init__.py b/maldump/parsers/__init__.py index 7455bdc..e69de29 100644 --- a/maldump/parsers/__init__.py +++ b/maldump/parsers/__init__.py @@ -1,21 +0,0 @@ -from . import kaitai -from .avast_parser import AvastParser -from .avg_parser import AVGParser -from .eset_parser import EsetParser -from .forticlient_parser import ForticlientParser -from .kaspersky_parser import KasperskyParser -from .malwarebytes_parser import MalwarebytesParser -from .mcafee_parser import McafeeParser -from .windef_parser import WindowsDefenderParser - -__all__ = [ - "AVGParser", - "AvastParser", - "EsetParser", - "ForticlientParser", - "KasperskyParser", - "MalwarebytesParser", - "McafeeParser", - "WindowsDefenderParser", - "kaitai", -]