diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e4207e..aa8377b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,12 +4,18 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.0.7] - 2024-05-12 + +### Added + +- Added a new function specific to VENDOR 15 based on insights from [videohelp](https://forum.videohelp.com/threads/414104-Impossible-situation-dumping-keys-using-virtual-Android#post2730673). +- Included a detailed process for extracting keys in offline mode. + ## [1.0.6] - 2024-04-26 ### Added - Added `mksrc` script to manually improve Android shell interaction. -- Added `editor` script for a text editor within the Android shell. ### Changed @@ -94,6 +100,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - Initial release of the project, laying the foundation for future enhancements and features. +[1.0.7]: https://github.com/hyugogirubato/KeyDive/releases/tag/v1.0.7 [1.0.6]: https://github.com/hyugogirubato/KeyDive/releases/tag/v1.0.6 [1.0.5]: https://github.com/hyugogirubato/KeyDive/releases/tag/v1.0.5 [1.0.4]: https://github.com/hyugogirubato/KeyDive/releases/tag/v1.0.4 diff --git a/README.md b/README.md index 2214974..b154584 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,18 @@ Follow these steps to set up KeyDive: This sequence ensures that the DRM-protected content is active and ready for key extraction by the time the KeyDive script is initiated, optimizing the extraction process. +### Offline Extraction Process + +For situations where internet access is limited or unavailable, KeyDive supports an offline extraction mode. This mode allows for the extraction of DRM keys without an active internet connection. Follow these steps to prepare: + +1. **Prepare the Android Device:** + - Install all necessary dependencies and tools while connected to the internet. Ensure that all software and libraries required by KeyDive are properly configured on the device. This includes making sure the device is fully prepared to handle DRM extraction in an offline environment. + +2. **Execute KeyDive in Offline Mode:** + - Once all the preparations are complete and the device is disconnected from the internet, run the KeyDive script to extract the Widevine L3 keys. Ensure that the DRM-protected content is ready and available on the device for extraction. + +For a detailed step-by-step guide on setting up and executing KeyDive without internet access, please refer to our dedicated document: [Offline Mode Detailed Guide](./docs/Axinom/OFFLINE.md). + ### Command-Line Options ```shell diff --git a/docs/Axinom/OFFLINE.md b/docs/Axinom/OFFLINE.md new file mode 100644 index 0000000..f22f88f --- /dev/null +++ b/docs/Axinom/OFFLINE.md @@ -0,0 +1,56 @@ +# Offline DRM Key Extraction for Axinom Content + +This project focuses on extracting DRM keys offline from streams protected by Axinom DRM. It involves patching an open-source application to customize stream definitions, disabling network connectivity checks, and optionally bypassing SSL pinning. Additionally, it includes steps for handling device provisioning requests using a fake server. + +## Prerequisites + +- Android Studio SDK to modify and build the APK. +- Frida setup on your device/emulator for runtime instrumentation. +- HTTP Toolkit for intercepting and modifying network traffic. +- Basic understanding of Android development and network protocols. + +## Setup + +### Step 1: Patch the APK + +1. Clone the repository of the open-source app you intend to patch. +2. Modify the app’s source code to: + - Define the correct stream URL. + - Disable any network connectivity checks in the app. For example, bypass methods that check for active internet connections. + ```shell + python3 builder_mobile.py + ``` +3. Build the modified APK and install it on your Android device or emulator. + ```shell + python3 patcher.py + ``` + +### Step 2: Bypass SSL Pinning (if necessary) + +If the app implements SSL pinning, follow the steps below to bypass it using Frida: + +1. Ensure Frida is installed on your device or emulator. +2. Use the script provided in the [Frida-CodeShare repository](https://github.com/hyugogirubato/Frida-CodeShare/tree/main/scripts/android-pinning) to intercept SSL pinning methods dynamically. +3. Run the script using the command: + ``` + frida -D "DEVICE_ID" -l "pinning.js" -f "PACKAGE_NAME" + ``` + Replace `"DEVICE_ID"` with your device or emulator ID and `"PACKAGE_NAME"` with the package name of your patched app. + +### Step 3: Setup Fake Server for Provisioning + +1. Setup a Python server to mimic the license server. This server should always respond with a 302 redirect loop, essentially providing an infinite timeout. + ```shell + python3 app.py + ``` +2. Implement the fake server with endpoints required for the DRM license and provisioning requests. + +### Step 4: Use HTTP Toolkit + +1. Install and set up HTTP Toolkit on your PC. +2. Import predefined rules to simulate the static responses needed for the app, like `manifest.mpd`. +3. Direct your app traffic through HTTP Toolkit to manipulate the responses as needed. + +## Running the App + +Launch the patched app on your device. Since the network checks are disabled, and the app is configured to use the fake server responses, it should function without real internet access, allowing for offline DRM key extraction. \ No newline at end of file diff --git a/docs/Axinom/patch/SampleChooserActivity.smali b/docs/Axinom/patch/SampleChooserActivity.smali new file mode 100644 index 0000000..5fac857 --- /dev/null +++ b/docs/Axinom/patch/SampleChooserActivity.smali @@ -0,0 +1,47 @@ +.method private isNetworkAvailable()Z + .registers 2 + + # const-string v0, "connectivity" + + # .line 139 + # invoke-virtual {p0, v0}, Lcom/axinom/drm/sample/activity/SampleChooserActivity;->getSystemService(Ljava/lang/String;)Ljava/lang/Object; + + # move-result-object v0 + + # check-cast v0, Landroid/net/ConnectivityManager; + + # if-eqz v0, :cond_f + + # .line 142 + # invoke-virtual {v0}, Landroid/net/ConnectivityManager;->getActiveNetworkInfo()Landroid/net/NetworkInfo; + + # move-result-object v0 + + # goto :goto_10 + + # :cond_f + # const/4 v0, 0x0 + + # :goto_10 + # if-eqz v0, :cond_1a + + # .line 144 + # invoke-virtual {v0}, Landroid/net/NetworkInfo;->isConnected()Z + + # move-result v0 + + # if-eqz v0, :cond_1a + + # const/4 v0, 0x1 + + # goto :goto_1b + + # :cond_1a + # const/4 v0, 0x0 + + # :goto_1b + + const/4 v0, 0x1 + + return v0 +.end method diff --git a/docs/Axinom/patch/axinom.apk b/docs/Axinom/patch/axinom.apk new file mode 100644 index 0000000..023f864 Binary files /dev/null and b/docs/Axinom/patch/axinom.apk differ diff --git a/docs/Axinom/patch/builder_mobile.py b/docs/Axinom/patch/builder_mobile.py new file mode 100644 index 0000000..2cdde13 --- /dev/null +++ b/docs/Axinom/patch/builder_mobile.py @@ -0,0 +1,47 @@ +from pathlib import Path + +import yaml + +# @Info: values to be patch +PATCH = { + "assets/samplelist.json": [ + [None, "samplelist.json"] + ], + "com/axinom/drm/sample/activity/SampleChooserActivity.smali": [ + ["SampleChooserActivity.smali", None] + ] +} + +# @Info: Keystore to sign the application +KEYSTORE = { + "algo": "RSA", + "size": 2048, + "sign": "SHA-256", + "validity": 365 * 25, + "password": "Axinom_PASSWORD", + "alias": "Axinom_DRM_DEMO", + "meta": { + "common_name": "Axinom", + "organizational_unit": "Front-End", + "organization": "Axinom", + "locality": "Tartu", + "state": "Tartumaa", + "country": "EE", + } +} + +# @Info: Info about application +METADATA = { + # "name": "Axinom DRM Sample Player", + "version": "202211021", + "source": "https://github.com/Axinom/drm-sample-player-android", + "input": "axinom.apk", + "output": "axinom_signed.apk", +} + +if __name__ == "__main__": + Path("config.yaml").write_text(yaml.dump({ + "metadata": METADATA, + "keystore": KEYSTORE, + "patch": PATCH + })) diff --git a/docs/Axinom/patch/patcher.py b/docs/Axinom/patch/patcher.py new file mode 100644 index 0000000..affe01e --- /dev/null +++ b/docs/Axinom/patch/patcher.py @@ -0,0 +1,260 @@ +import hashlib +import json +import os +import re +import shutil +from pathlib import Path + +import xmltodict +import yaml + + +def any2str(data: any) -> str: + if isinstance(data, (bytes, bytearray)): + data = data.decode("utf-8") + + if isinstance(data, (dict, list)): + data = json.dumps(data, indent=2, separators=(",", ":")) + + return str(data) + + +class Keystore: + + def __init__( + self, + algo: str = "RSA", + size: int = 2048, + sign: str = "SHA-256", + validity: int = 365, + password: str = None, + alias: str = None, + meta: dict = None, + path: Path = Path("..") + ): + assert path.is_dir(), "Invalid Dir Path" + assert algo in ["RSA", "EC", "DSA"], "Invalid Algorithm" + assert sign in ["MD5", "SHA-1", "SHA-256", "SHA-512"], "Invalid Signature" + + if algo == "RSA": + assert size in [1024, 2048, 3072, 4096], "Invalid RSA Size" + assert sign in ["MD5", "SHA-1", "SHA-256", "SHA-512"], "Invalid RSA Signature" + elif algo == "EC": + assert size in [192, 224, 256, 384, 521], "Invalid EC Size" + assert sign in ["SHA-256", "SHA-512"], "Invalid EC Signature" + elif algo == "DSA": + assert size in [1024], "Invalid DSA Size" + assert sign in ["SHA-1"], "Invalid DSA Signature" + + self.algorithm = algo + self.size = size + self.signature = "{}with{}".format( + sign.replace("-", ""), + "ECDSA" if algo == "EC" else algo + ) + self.digest = sign + self.validity = validity + meta = meta if meta else {} + self.metadata = { + "common_name": meta.get("common_name", "Unknown"), + "organizational_unit": meta.get("organizational_unit", "Unknown"), + "organization": meta.get("organization", "Unknown"), + "locality": meta.get("locality", "Unknown"), + "state": meta.get("state", "Unknown"), + "country": meta.get("country", "Unknown"), + } + + match = re.search(r'[\s:]?([a-zA-Z]+)', self.metadata["common_name"]) + name = re.sub(r'[^A-Za-z0-9]', "", match.group(1)).lower() if match else "keystore" + self.path = path / f"{name}_{algo.lower()}.p12" + self.password = password or f"{name}_password" + self.alias = alias or f"{name}_alias" + + def __repr__(self) -> str: + return json.dumps({ + "path": str(self.path), + "algorithm": self.algorithm, + "size": self.size, + "signature": self.signature, + "digest": self.digest, + "validity": self.validity, + "password": self.password, + "alias": self.alias, + "metadata": self.metadata + }, indent=2) + + def sign(self, path: Path) -> None: + assert path.is_file() and path.suffix == ".apk", "Invalid APK Path" + + if not self.path.is_file(): + tmp = Path("keystore.jks") + os.system( + 'keytool -genkeypair -keystore "{}" -alias "{}" -keyalg "{}" -keysize "{}" -sigalg "{}" -validity "{}" -storepass "{}" -keypass "{}" -dname "CN=\\"{}\\", OU=\\"{}\\", O=\\"{}\\", L=\\"{}\\", ST=\\"{}\\", C=\\"{}\\"" -noprompt'.format( + tmp, self.alias, self.algorithm, self.size, self.signature, + self.validity, self.password, self.password, self.metadata["common_name"], + self.metadata["organizational_unit"], self.metadata["organization"], + self.metadata["locality"], self.metadata["state"], self.metadata["country"] + )) + + os.system( + 'keytool -importkeystore -srckeystore "{}" -srcstorepass "{}" -destkeystore "{}" -deststoretype "PKCS12" -deststorepass "{}" -destkeypass "{}" -srcalias "{}"'.format( + tmp, self.password, self.path, self.password, self.password, self.alias + )) + tmp.unlink(missing_ok=True) + os.system('apksigner sign --ks "{}" --ks-key-alias "{}" --ks-pass "pass:{}" --key-pass "pass:{}" "{}"'.format( + self.path, self.alias, self.password, self.password, path + )) + Path(str(path) + ".idsig").unlink(missing_ok=True) + + def info(self, path: Path) -> None: + assert path.is_file() and path.suffix == ".apk", "Invalid APK Path" + os.system(f'apksigner verify --print-certs "{path}"') + + +class ApkTool: + + def __init__(self, instance: Path = Path(".apktool")): + self.instance = instance + + def decompile(self, path: Path) -> None: + assert path.is_file() and path.suffix == ".apk", "Invalid APK Path" + if not self.instance.is_dir(): + os.system(f'apktool d "{path}" -o "{self.instance}" -f --no-crunch --only-main-classes') + + def compile(self, path: Path) -> None: + assert path.suffix == ".apk", "Invalid APK Path" + if not path.is_file(): + assert self.instance.is_dir(), "Invalid ApkTool Path" + tmp = Path("unaligned.apk") + + os.system(f'apktool b "{self.instance}" -o "{tmp}" -f --no-crunch') + if tmp.is_file(): os.system(f'zipalign -f -p "4" "{tmp}" "{path}"') + if path.is_file(): shutil.rmtree(self.instance, ignore_errors=True) + tmp.unlink(missing_ok=True) + + +def rename_app(parent: Path, name: str) -> None: + manifest_path = parent / "AndroidManifest.xml" + if not manifest_path.is_file(): + raise FileNotFoundError(manifest_path) + + manifest_dict = xmltodict.parse(manifest_path.read_bytes(), encoding="utf-8") + value = str(manifest_dict["manifest"]["application"]["@android:label"]) + if value.startswith("@string/"): + key = value.split("@string/")[1] + + source = None + for path in (parent / "res").iterdir(): + strings_path = path / "strings.xml" + if "values" in str(path) and strings_path.is_file(): + strings_dict = xmltodict.parse(strings_path.read_bytes(), encoding="utf-8") + + for item in strings_dict["resources"]["string"]: + if isinstance(item, dict) and item["@name"] == key: + source = item["#text"] + print(f"I: Patching {strings_path.name} ({strings_path.parent})") + if source != name: + item["#text"] = name + strings_path.write_bytes( + xmltodict.unparse(strings_dict, encoding="utf-8", pretty=True).encode("utf-8")) + break + if not source: + raise ImportError(value) + else: + manifest_dict["manifest"]["application"]["@android:label"] = name + manifest_path.write_bytes(xmltodict.unparse(manifest_dict, encoding="utf-8", pretty=True).encode("utf-8")) + print(f"I: Patching {manifest_path.name} ({manifest_path.parent})") + + +if __name__ == "__main__": + config = Path("config.yaml") + if not config.is_file(): + config = Path(input("Config Path: ")) + if not config.is_file(): + raise FileNotFoundError(config) + + content = yaml.safe_load(config.read_text()) + + apktool = ApkTool() + jks = Keystore(**content["keystore"]) + src = Path(content["metadata"]["input"]) + opt = Path(content["metadata"]["output"]) + + for key, value in content["metadata"].items(): + print(f"I: {key.capitalize()}: {value}") + + if not opt.is_file(): + apktool.decompile(src) + + # @Info: Patch apk + for key, value in content["patch"].items(): # {Path: list[tuple]} + + path = apktool.instance / key + if not path.is_file(): + exist = False + for subp in apktool.instance.iterdir(): + path = subp / key + if path.is_file(): + exist = True + break + + if not exist: + raise FileNotFoundError(key) + + src_data = path.read_text() + for v in value: + if v[0] is None: + if isinstance(v[1], str): + # @Info: Replace complet file using [None, Path] + v[1] = Path(v[1]) + if not v[1].is_file(): + raise FileNotFoundError(v[1]) + src_data = v[1].read_text() + elif v[1] is None: + # @Info: Replace with empty file + src_data = "" + else: + # @Info: Replace with custom char + src_data = any2str(v[1]) + elif v[1] is None: + # @Info: Replace functon using [Path, None] + if not isinstance(v[0], str): + raise ImportError(v[0]) + + v[0] = Path(v[0]) + if not v[0].is_file(): + raise FileNotFoundError(v[0]) + + opt_data = v[0].read_text() + if opt_data not in src_data: + try: + keys = opt_data.split("\n") + start = next(filter(None, keys), None) + stop = next(filter(None, reversed(keys)), None) + start_index = src_data.index(start) + stop_index = src_data.index(stop, start_index) + len(stop) + src_data = src_data.replace(src_data[start_index:stop_index], opt_data) + except Exception as e: + raise ValueError(v[0]) + else: + # @Info: Replace char using [str, str] + if not v[0] in src_data and not v[1] in src_data: + raise ImportError(v[0]) + src_data = src_data.replace(*v) + + path.write_text(src_data) + print(f"I: Patching {path.name} ({path.parent})") + + # @Info: Rename apk + name = content["metadata"].get("name") + if name: + rename_app(apktool.instance, name) + + apktool.compile(opt) + print(f"I: Keystore: {jks.path}") + print(f"I: Validity: {jks.validity}") + jks.sign(opt) + + jks.info(opt) + + print(f'I: MD5: {hashlib.md5(opt.read_bytes()).hexdigest()}') diff --git a/docs/Axinom/patch/samplelist.json b/docs/Axinom/patch/samplelist.json new file mode 100644 index 0000000..374c712 --- /dev/null +++ b/docs/Axinom/patch/samplelist.json @@ -0,0 +1,9 @@ +[ + { + "title": "Axinom demo video - single key (DASH; cenc)", + "videoUrl": "https://media.axprod.net/VTB/DrmQuickStart/AxinomDemoVideo-SingleKey/Encrypted_Cenc/Manifest.mpd", + "drmScheme": "widevine", + "licenseServer": "https://drm-widevine-licensing.axtest.net/AcquireLicense", + "licenseToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ2ZXJzaW9uIjoxLCJjb21fa2V5X2lkIjoiNjllNTQwODgtZTllMC00NTMwLThjMWEtMWViNmRjZDBkMTRlIiwibWVzc2FnZSI6eyJ2ZXJzaW9uIjoyLCJ0eXBlIjoiZW50aXRsZW1lbnRfbWVzc2FnZSIsImxpY2Vuc2UiOnsiYWxsb3dfcGVyc2lzdGVuY2UiOnRydWV9LCJjb250ZW50X2tleXNfc291cmNlIjp7ImlubGluZSI6W3siaWQiOiIyMTFhYzFkYy1jOGEyLTQ1NzUtYmFmNy1mYTRiYTU2YzM4YWMiLCJ1c2FnZV9wb2xpY3kiOiJUaGVPbmVQb2xpY3kifV19LCJjb250ZW50X2tleV91c2FnZV9wb2xpY2llcyI6W3sibmFtZSI6IlRoZU9uZVBvbGljeSIsInBsYXlyZWFkeSI6eyJwbGF5X2VuYWJsZXJzIjpbIjc4NjYyN0Q4LUMyQTYtNDRCRS04Rjg4LTA4QUUyNTVCMDFBNyJdfX1dfX0.D9FM9sbTFxBmcCOC8yMHrEtTwm0zy6ejZUCrlJbHz_U" + } +] \ No newline at end of file diff --git a/docs/Axinom/server/HTTPToolkit_2024-04-17_16-19.htkrules b/docs/Axinom/server/HTTPToolkit_2024-04-17_16-19.htkrules new file mode 100644 index 0000000..968ccb9 --- /dev/null +++ b/docs/Axinom/server/HTTPToolkit_2024-04-17_16-19.htkrules @@ -0,0 +1 @@ +{"id":"root","title":"HTTP Toolkit Rules","isRoot":true,"items":[{"id":"7421bc54-c600-4464-b0dc-25a56a37c4c6","type":"http","activated":true,"matchers":[{"type":"wildcard"},{"host":"www.googleapis.com","type":"host"}],"completionChecker":{"type":"always"},"handler":{"uiType":"forward-to-host","type":"passthrough","forwarding":{"targetHost":"http://127.0.0.1:9090","updateHostHeader":true}}},{"id":"fd34080d-5f03-4624-9664-d8478d48253c","type":"http","activated":true,"matchers":[{"type":"wildcard"},{"path":"https://media.axprod.net/VTB/DrmQuickStart/AxinomDemoVideo-SingleKey/Encrypted_Cenc/Manifest.mpd","type":"simple-path"}],"completionChecker":{"type":"always"},"handler":{"data":{"type":"Buffer","data":[60,63,120,109,108,32,118,101,114,115,105,111,110,61,34,49,46,48,34,32,101,110,99,111,100,105,110,103,61,34,117,116,102,45,56,34,63,62,10,60,77,80,68,32,120,109,108,110,115,61,34,117,114,110,58,109,112,101,103,58,100,97,115,104,58,115,99,104,101,109,97,58,109,112,100,58,50,48,49,49,34,32,109,105,110,66,117,102,102,101,114,84,105,109,101,61,34,80,84,49,46,53,48,48,83,34,32,116,121,112,101,61,34,115,116,97,116,105,99,34,32,109,101,100,105,97,80,114,101,115,101,110,116,97,116,105,111,110,68,117,114,97,116,105,111,110,61,34,80,84,48,72,48,77,53,50,46,50,48,57,83,34,32,109,97,120,83,101,103,109,101,110,116,68,117,114,97,116,105,111,110,61,34,80,84,48,72,48,77,52,46,48,49,49,83,34,32,112,114,111,102,105,108,101,115,61,34,117,114,110,58,109,112,101,103,58,100,97,115,104,58,112,114,111,102,105,108,101,58,105,115,111,102,102,45,108,105,118,101,58,50,48,49,49,44,104,116,116,112,58,47,47,100,97,115,104,105,102,46,111,114,103,47,103,117,105,100,101,108,105,110,101,115,47,100,97,115,104,50,54,52,34,32,120,109,108,110,115,58,99,101,110,99,61,34,117,114,110,58,109,112,101,103,58,99,101,110,99,58,50,48,49,51,34,62,10,9,60,80,101,114,105,111,100,32,100,117,114,97,116,105,111,110,61,34,80,84,48,72,48,77,53,50,46,50,48,57,83,34,62,10,9,9,60,33,45,45,65,120,105,110,111,109,32,77,97,107,101,109,101,100,105,97,32,118,52,46,49,46,50,45,48,48,52,54,55,55,45,57,98,99,51,56,101,48,32,116,97,114,103,101,116,105,110,103,32,71,101,110,101,114,97,108,32,80,117,114,112,111,115,101,32,77,101,100,105,97,32,70,111,114,109,97,116,32,115,112,101,99,105,102,105,99,97,116,105,111,110,32,118,49,48,10,102,102,109,112,101,103,32,118,101,114,115,105,111,110,32,78,45,57,48,48,54,57,45,103,100,100,56,51,53,49,98,49,49,56,45,115,104,101,114,112,121,97,32,67,111,112,121,114,105,103,104,116,32,40,99,41,32,50,48,48,48,45,50,48,49,56,32,116,104,101,32,70,70,109,112,101,103,32,100,101,118,101,108,111,112,101,114,115,10,120,50,54,53,32,91,105,110,102,111,93,58,32,72,69,86,67,32,101,110,99,111,100,101,114,32,118,101,114,115,105,111,110,32,50,46,52,43,49,52,45,98,99,48,101,57,98,100,55,99,48,56,102,53,100,100,99,10,120,50,54,52,32,48,46,49,53,48,46,50,56,51,51,32,100,102,55,57,48,54,55,10,77,80,52,66,111,120,32,45,32,71,80,65,67,32,118,101,114,115,105,111,110,32,48,46,55,46,50,45,68,69,86,45,114,101,118,53,51,57,45,103,102,102,53,57,100,102,97,48,45,109,97,115,116,101,114,10,77,101,100,105,97,73,110,102,111,76,105,98,32,45,32,118,48,46,55,46,57,54,10,45,45,62,10,9,9,60,65,100,97,112,116,97,116,105,111,110,83,101,116,32,115,101,103,109,101,110,116,65,108,105,103,110,109,101,110,116,61,34,116,114,117,101,34,32,109,97,120,87,105,100,116,104,61,34,49,57,50,48,34,32,109,97,120,72,101,105,103,104,116,61,34,49,48,56,48,34,32,109,97,120,70,114,97,109,101,82,97,116,101,61,34,50,52,34,32,112,97,114,61,34,49,54,58,57,34,32,108,97,110,103,61,34,117,110,100,34,32,103,114,111,117,112,61,34,49,34,32,115,101,108,101,99,116,105,111,110,80,114,105,111,114,105,116,121,61,34,48,34,62,10,9,9,9,60,67,111,110,116,101,110,116,80,114,111,116,101,99,116,105,111,110,32,115,99,104,101,109,101,73,100,85,114,105,61,34,117,114,110,58,109,112,101,103,58,100,97,115,104,58,109,112,52,112,114,111,116,101,99,116,105,111,110,58,50,48,49,49,34,32,118,97,108,117,101,61,34,99,101,110,99,34,32,99,101,110,99,58,100,101,102,97,117,108,116,95,75,73,68,61,34,50,49,49,97,99,49,100,99,45,99,56,97,50,45,52,53,55,53,45,98,97,102,55,45,102,97,52,98,97,53,54,99,51,56,97,99,34,32,47,62,10,9,9,9,60,67,111,110,116,101,110,116,80,114,111,116,101,99,116,105,111,110,32,118,97,108,117,101,61,34,77,83,80,82,32,50,46,48,34,32,115,99,104,101,109,101,73,100,85,114,105,61,34,117,114,110,58,117,117,105,100,58,57,97,48,52,102,48,55,57,45,57,56,52,48,45,52,50,56,54,45,97,98,57,50,45,101,54,53,98,101,48,56,56,53,102,57,53,34,62,10,9,9,9,9,60,99,101,110,99,58,112,115,115,104,62,65,65,65,66,53,72,66,122,99,50,103,65,65,65,65,65,109,103,84,119,101,90,104,65,81,111,97,114,107,117,90,98,52,73,104,102,108,81,65,65,65,99,84,69,65,81,65,65,65,81,65,66,65,76,111,66,80,65,66,88,65,70,73,65,84,81,66,73,65,69,85,65,81,81,66,69,65,69,85,65,85,103,65,103,65,72,103,65,98,81,66,115,65,71,52,65,99,119,65,57,65,67,73,65,97,65,66,48,65,72,81,65,99,65,65,54,65,67,56,65,76,119,66,122,65,71,77,65,97,65,66,108,65,71,48,65,89,81,66,122,65,67,52,65,98,81,66,112,65,71,77,65,99,103,66,118,65,72,77,65,98,119,66,109,65,72,81,65,76,103,66,106,65,71,56,65,98,81,65,118,65,69,81,65,85,103,66,78,65,67,56,65,77,103,65,119,65,68,65,65,78,119,65,118,65,68,65,65,77,119,65,118,65,70,65,65,98,65,66,104,65,72,107,65,85,103,66,108,65,71,69,65,90,65,66,53,65,69,103,65,90,81,66,104,65,71,81,65,90,81,66,121,65,67,73,65,73,65,66,50,65,71,85,65,99,103,66,122,65,71,107,65,98,119,66,117,65,68,48,65,73,103,65,48,65,67,52,65,77,65,65,117,65,68,65,65,76,103,65,119,65,67,73,65,80,103,65,56,65,69,81,65,81,81,66,85,65,69,69,65,80,103,65,56,65,70,65,65,85,103,66,80,65,70,81,65,82,81,66,68,65,70,81,65,83,81,66,79,65,69,89,65,84,119,65,43,65,68,119,65,83,119,66,70,65,70,107,65,84,65,66,70,65,69,52,65,80,103,65,120,65,68,89,65,80,65,65,118,65,69,115,65,82,81,66,90,65,69,119,65,82,81,66,79,65,68,52,65,80,65,66,66,65,69,119,65,82,119,66,74,65,69,81,65,80,103,66,66,65,69,85,65,85,119,66,68,65,70,81,65,85,103,65,56,65,67,56,65,81,81,66,77,65,69,99,65,83,81,66,69,65,68,52,65,80,65,65,118,65,70,65,65,85,103,66,80,65,70,81,65,82,81,66,68,65,70,81,65,83,81,66,79,65,69,89,65,84,119,65,43,65,68,119,65,83,119,66,74,65,69,81,65,80,103,65,122,65,69,48,65,82,81,66,104,65,69,107,65,89,81,66,77,65,69,107,65,90,65,66,86,65,70,99,65,78,103,65,53,65,67,56,65,99,65,66,77,65,72,65,65,86,119,66,51,65,68,81,65,99,103,66,66,65,68,48,65,80,81,65,56,65,67,56,65,83,119,66,74,65,69,81,65,80,103,65,56,65,67,56,65,82,65,66,66,65,70,81,65,81,81,65,43,65,68,119,65,76,119,66,88,65,70,73,65,84,81,66,73,65,69,85,65,81,81,66,69,65,69,85,65,85,103,65,43,65,65,61,61,60,47,99,101,110,99,58,112,115,115,104,62,10,9,9,9,9,60,112,114,111,32,120,109,108,110,115,61,34,117,114,110,58,109,105,99,114,111,115,111,102,116,58,112,108,97,121,114,101,97,100,121,34,62,120,65,69,65,65,65,69,65,65,81,67,54,65,84,119,65,86,119,66,83,65,69,48,65,83,65,66,70,65,69,69,65,82,65,66,70,65,70,73,65,73,65,66,52,65,71,48,65,98,65,66,117,65,72,77,65,80,81,65,105,65,71,103,65,100,65,66,48,65,72,65,65,79,103,65,118,65,67,56,65,99,119,66,106,65,71,103,65,90,81,66,116,65,71,69,65,99,119,65,117,65,71,48,65,97,81,66,106,65,72,73,65,98,119,66,122,65,71,56,65,90,103,66,48,65,67,52,65,89,119,66,118,65,71,48,65,76,119,66,69,65,70,73,65,84,81,65,118,65,68,73,65,77,65,65,119,65,68,99,65,76,119,65,119,65,68,77,65,76,119,66,81,65,71,119,65,89,81,66,53,65,70,73,65,90,81,66,104,65,71,81,65,101,81,66,73,65,71,85,65,89,81,66,107,65,71,85,65,99,103,65,105,65,67,65,65,100,103,66,108,65,72,73,65,99,119,66,112,65,71,56,65,98,103,65,57,65,67,73,65,78,65,65,117,65,68,65,65,76,103,65,119,65,67,52,65,77,65,65,105,65,68,52,65,80,65,66,69,65,69,69,65,86,65,66,66,65,68,52,65,80,65,66,81,65,70,73,65,84,119,66,85,65,69,85,65,81,119,66,85,65,69,107,65,84,103,66,71,65,69,56,65,80,103,65,56,65,69,115,65,82,81,66,90,65,69,119,65,82,81,66,79,65,68,52,65,77,81,65,50,65,68,119,65,76,119,66,76,65,69,85,65,87,81,66,77,65,69,85,65,84,103,65,43,65,68,119,65,81,81,66,77,65,69,99,65,83,81,66,69,65,68,52,65,81,81,66,70,65,70,77,65,81,119,66,85,65,70,73,65,80,65,65,118,65,69,69,65,84,65,66,72,65,69,107,65,82,65,65,43,65,68,119,65,76,119,66,81,65,70,73,65,84,119,66,85,65,69,85,65,81,119,66,85,65,69,107,65,84,103,66,71,65,69,56,65,80,103,65,56,65,69,115,65,83,81,66,69,65,68,52,65,77,119,66,78,65,69,85,65,89,81,66,74,65,71,69,65,84,65,66,74,65,71,81,65,86,81,66,88,65,68,89,65,79,81,65,118,65,72,65,65,84,65,66,119,65,70,99,65,100,119,65,48,65,72,73,65,81,81,65,57,65,68,48,65,80,65,65,118,65,69,115,65,83,81,66,69,65,68,52,65,80,65,65,118,65,69,81,65,81,81,66,85,65,69,69,65,80,103,65,56,65,67,56,65,86,119,66,83,65,69,48,65,83,65,66,70,65,69,69,65,82,65,66,70,65,70,73,65,80,103,65,61,60,47,112,114,111,62,10,9,9,9,60,47,67,111,110,116,101,110,116,80,114,111,116,101,99,116,105,111,110,62,10,9,9,9,60,67,111,110,116,101,110,116,80,114,111,116,101,99,116,105,111,110,32,118,97,108,117,101,61,34,87,105,100,101,118,105,110,101,34,32,115,99,104,101,109,101,73,100,85,114,105,61,34,117,114,110,58,117,117,105,100,58,101,100,101,102,56,98,97,57,45,55,57,100,54,45,52,97,99,101,45,97,51,99,56,45,50,55,100,99,100,53,49,100,50,49,101,100,34,62,10,9,9,9,9,60,99,101,110,99,58,112,115,115,104,62,65,65,65,65,78,72,66,122,99,50,103,65,65,65,65,65,55,101,43,76,113,88,110,87,83,115,54,106,121,67,102,99,49,82,48,104,55,81,65,65,65,66,81,73,65,82,73,81,73,82,114,66,51,77,105,105,82,88,87,54,57,47,112,76,112,87,119,52,114,65,61,61,60,47,99,101,110,99,58,112,115,115,104,62,10,9,9,9,60,47,67,111,110,116,101,110,116,80,114,111,116,101,99,116,105,111,110,62,10,9,9,9,60,82,111,108,101,32,115,99,104,101,109,101,73,100,85,114,105,61,34,117,114,110,58,109,112,101,103,58,100,97,115,104,58,114,111,108,101,58,50,48,49,49,34,32,118,97,108,117,101,61,34,109,97,105,110,34,32,47,62,10,9,9,9,60,83,101,103,109,101,110,116,84,101,109,112,108,97,116,101,32,109,101,100,105,97,61,34,36,82,101,112,114,101,115,101,110,116,97,116,105,111,110,73,68,36,47,36,78,117,109,98,101,114,37,48,52,100,36,46,109,52,115,34,32,116,105,109,101,115,99,97,108,101,61,34,50,52,34,32,115,116,97,114,116,78,117,109,98,101,114,61,34,49,34,32,100,117,114,97,116,105,111,110,61,34,57,54,34,32,105,110,105,116,105,97,108,105,122,97,116,105,111,110,61,34,36,82,101,112,114,101,115,101,110,116,97,116,105,111,110,73,68,36,47,105,110,105,116,46,109,112,52,34,32,47,62,10,9,9,9,60,82,101,112,114,101,115,101,110,116,97,116,105,111,110,32,105,100,61,34,49,34,32,109,105,109,101,84,121,112,101,61,34,118,105,100,101,111,47,109,112,52,34,32,99,111,100,101,99,115,61,34,97,118,99,49,46,54,52,48,48,49,53,34,32,119,105,100,116,104,61,34,53,49,50,34,32,104,101,105,103,104,116,61,34,50,56,56,34,32,102,114,97,109,101,82,97,116,101,61,34,50,52,34,32,115,97,114,61,34,49,58,49,34,32,115,116,97,114,116,87,105,116,104,83,65,80,61,34,49,34,32,98,97,110,100,119,105,100,116,104,61,34,51,53,56,55,51,51,34,62,60,47,82,101,112,114,101,115,101,110,116,97,116,105,111,110,62,10,9,9,9,60,82,101,112,114,101,115,101,110,116,97,116,105,111,110,32,105,100,61,34,50,34,32,109,105,109,101,84,121,112,101,61,34,118,105,100,101,111,47,109,112,52,34,32,99,111,100,101,99,115,61,34,97,118,99,49,46,54,52,48,48,49,69,34,32,119,105,100,116,104,61,34,54,52,48,34,32,104,101,105,103,104,116,61,34,51,54,48,34,32,102,114,97,109,101,82,97,116,101,61,34,50,52,34,32,115,97,114,61,34,49,58,49,34,32,115,116,97,114,116,87,105,116,104,83,65,80,61,34,49,34,32,98,97,110,100,119,105,100,116,104,61,34,54,56,53,49,50,50,34,62,60,47,82,101,112,114,101,115,101,110,116,97,116,105,111,110,62,10,9,9,9,60,82,101,112,114,101,115,101,110,116,97,116,105,111,110,32,105,100,61,34,51,34,32,109,105,109,101,84,121,112,101,61,34,118,105,100,101,111,47,109,112,52,34,32,99,111,100,101,99,115,61,34,97,118,99,49,46,54,52,48,48,49,69,34,32,119,105,100,116,104,61,34,56,53,50,34,32,104,101,105,103,104,116,61,34,52,56,48,34,32,102,114,97,109,101,82,97,116,101,61,34,50,52,34,32,115,97,114,61,34,54,52,48,58,54,51,57,34,32,115,116,97,114,116,87,105,116,104,83,65,80,61,34,49,34,32,98,97,110,100,119,105,100,116,104,61,34,49,48,49,53,50,56,53,34,62,60,47,82,101,112,114,101,115,101,110,116,97,116,105,111,110,62,10,9,9,9,60,82,101,112,114,101,115,101,110,116,97,116,105,111,110,32,105,100,61,34,52,34,32,109,105,109,101,84,121,112,101,61,34,118,105,100,101,111,47,109,112,52,34,32,99,111,100,101,99,115,61,34,97,118,99,49,46,54,52,48,48,49,70,34,32,119,105,100,116,104,61,34,49,50,56,48,34,32,104,101,105,103,104,116,61,34,55,50,48,34,32,102,114,97,109,101,82,97,116,101,61,34,50,52,34,32,115,97,114,61,34,49,58,49,34,32,115,116,97,114,116,87,105,116,104,83,65,80,61,34,49,34,32,98,97,110,100,119,105,100,116,104,61,34,49,55,52,51,55,48,52,34,62,60,47,82,101,112,114,101,115,101,110,116,97,116,105,111,110,62,10,9,9,9,60,82,101,112,114,101,115,101,110,116,97,116,105,111,110,32,105,100,61,34,53,34,32,109,105,109,101,84,121,112,101,61,34,118,105,100,101,111,47,109,112,52,34,32,99,111,100,101,99,115,61,34,97,118,99,49,46,54,52,48,48,50,56,34,32,119,105,100,116,104,61,34,49,57,50,48,34,32,104,101,105,103,104,116,61,34,49,48,56,48,34,32,102,114,97,109,101,82,97,116,101,61,34,50,52,34,32,115,97,114,61,34,49,58,49,34,32,115,116,97,114,116,87,105,116,104,83,65,80,61,34,49,34,32,98,97,110,100,119,105,100,116,104,61,34,50,52,50,51,49,49,49,34,62,60,47,82,101,112,114,101,115,101,110,116,97,116,105,111,110,62,10,9,9,60,47,65,100,97,112,116,97,116,105,111,110,83,101,116,62,10,9,9,60,65,100,97,112,116,97,116,105,111,110,83,101,116,32,115,101,103,109,101,110,116,65,108,105,103,110,109,101,110,116,61,34,116,114,117,101,34,32,108,97,110,103,61,34,117,110,100,34,32,103,114,111,117,112,61,34,50,34,32,115,101,108,101,99,116,105,111,110,80,114,105,111,114,105,116,121,61,34,48,34,62,10,9,9,9,60,67,111,110,116,101,110,116,80,114,111,116,101,99,116,105,111,110,32,115,99,104,101,109,101,73,100,85,114,105,61,34,117,114,110,58,109,112,101,103,58,100,97,115,104,58,109,112,52,112,114,111,116,101,99,116,105,111,110,58,50,48,49,49,34,32,118,97,108,117,101,61,34,99,101,110,99,34,32,99,101,110,99,58,100,101,102,97,117,108,116,95,75,73,68,61,34,50,49,49,97,99,49,100,99,45,99,56,97,50,45,52,53,55,53,45,98,97,102,55,45,102,97,52,98,97,53,54,99,51,56,97,99,34,32,47,62,10,9,9,9,60,67,111,110,116,101,110,116,80,114,111,116,101,99,116,105,111,110,32,118,97,108,117,101,61,34,77,83,80,82,32,50,46,48,34,32,115,99,104,101,109,101,73,100,85,114,105,61,34,117,114,110,58,117,117,105,100,58,57,97,48,52,102,48,55,57,45,57,56,52,48,45,52,50,56,54,45,97,98,57,50,45,101,54,53,98,101,48,56,56,53,102,57,53,34,62,10,9,9,9,9,60,99,101,110,99,58,112,115,115,104,62,65,65,65,66,53,72,66,122,99,50,103,65,65,65,65,65,109,103,84,119,101,90,104,65,81,111,97,114,107,117,90,98,52,73,104,102,108,81,65,65,65,99,84,69,65,81,65,65,65,81,65,66,65,76,111,66,80,65,66,88,65,70,73,65,84,81,66,73,65,69,85,65,81,81,66,69,65,69,85,65,85,103,65,103,65,72,103,65,98,81,66,115,65,71,52,65,99,119,65,57,65,67,73,65,97,65,66,48,65,72,81,65,99,65,65,54,65,67,56,65,76,119,66,122,65,71,77,65,97,65,66,108,65,71,48,65,89,81,66,122,65,67,52,65,98,81,66,112,65,71,77,65,99,103,66,118,65,72,77,65,98,119,66,109,65,72,81,65,76,103,66,106,65,71,56,65,98,81,65,118,65,69,81,65,85,103,66,78,65,67,56,65,77,103,65,119,65,68,65,65,78,119,65,118,65,68,65,65,77,119,65,118,65,70,65,65,98,65,66,104,65,72,107,65,85,103,66,108,65,71,69,65,90,65,66,53,65,69,103,65,90,81,66,104,65,71,81,65,90,81,66,121,65,67,73,65,73,65,66,50,65,71,85,65,99,103,66,122,65,71,107,65,98,119,66,117,65,68,48,65,73,103,65,48,65,67,52,65,77,65,65,117,65,68,65,65,76,103,65,119,65,67,73,65,80,103,65,56,65,69,81,65,81,81,66,85,65,69,69,65,80,103,65,56,65,70,65,65,85,103,66,80,65,70,81,65,82,81,66,68,65,70,81,65,83,81,66,79,65,69,89,65,84,119,65,43,65,68,119,65,83,119,66,70,65,70,107,65,84,65,66,70,65,69,52,65,80,103,65,120,65,68,89,65,80,65,65,118,65,69,115,65,82,81,66,90,65,69,119,65,82,81,66,79,65,68,52,65,80,65,66,66,65,69,119,65,82,119,66,74,65,69,81,65,80,103,66,66,65,69,85,65,85,119,66,68,65,70,81,65,85,103,65,56,65,67,56,65,81,81,66,77,65,69,99,65,83,81,66,69,65,68,52,65,80,65,65,118,65,70,65,65,85,103,66,80,65,70,81,65,82,81,66,68,65,70,81,65,83,81,66,79,65,69,89,65,84,119,65,43,65,68,119,65,83,119,66,74,65,69,81,65,80,103,65,122,65,69,48,65,82,81,66,104,65,69,107,65,89,81,66,77,65,69,107,65,90,65,66,86,65,70,99,65,78,103,65,53,65,67,56,65,99,65,66,77,65,72,65,65,86,119,66,51,65,68,81,65,99,103,66,66,65,68,48,65,80,81,65,56,65,67,56,65,83,119,66,74,65,69,81,65,80,103,65,56,65,67,56,65,82,65,66,66,65,70,81,65,81,81,65,43,65,68,119,65,76,119,66,88,65,70,73,65,84,81,66,73,65,69,85,65,81,81,66,69,65,69,85,65,85,103,65,43,65,65,61,61,60,47,99,101,110,99,58,112,115,115,104,62,10,9,9,9,9,60,112,114,111,32,120,109,108,110,115,61,34,117,114,110,58,109,105,99,114,111,115,111,102,116,58,112,108,97,121,114,101,97,100,121,34,62,120,65,69,65,65,65,69,65,65,81,67,54,65,84,119,65,86,119,66,83,65,69,48,65,83,65,66,70,65,69,69,65,82,65,66,70,65,70,73,65,73,65,66,52,65,71,48,65,98,65,66,117,65,72,77,65,80,81,65,105,65,71,103,65,100,65,66,48,65,72,65,65,79,103,65,118,65,67,56,65,99,119,66,106,65,71,103,65,90,81,66,116,65,71,69,65,99,119,65,117,65,71,48,65,97,81,66,106,65,72,73,65,98,119,66,122,65,71,56,65,90,103,66,48,65,67,52,65,89,119,66,118,65,71,48,65,76,119,66,69,65,70,73,65,84,81,65,118,65,68,73,65,77,65,65,119,65,68,99,65,76,119,65,119,65,68,77,65,76,119,66,81,65,71,119,65,89,81,66,53,65,70,73,65,90,81,66,104,65,71,81,65,101,81,66,73,65,71,85,65,89,81,66,107,65,71,85,65,99,103,65,105,65,67,65,65,100,103,66,108,65,72,73,65,99,119,66,112,65,71,56,65,98,103,65,57,65,67,73,65,78,65,65,117,65,68,65,65,76,103,65,119,65,67,52,65,77,65,65,105,65,68,52,65,80,65,66,69,65,69,69,65,86,65,66,66,65,68,52,65,80,65,66,81,65,70,73,65,84,119,66,85,65,69,85,65,81,119,66,85,65,69,107,65,84,103,66,71,65,69,56,65,80,103,65,56,65,69,115,65,82,81,66,90,65,69,119,65,82,81,66,79,65,68,52,65,77,81,65,50,65,68,119,65,76,119,66,76,65,69,85,65,87,81,66,77,65,69,85,65,84,103,65,43,65,68,119,65,81,81,66,77,65,69,99,65,83,81,66,69,65,68,52,65,81,81,66,70,65,70,77,65,81,119,66,85,65,70,73,65,80,65,65,118,65,69,69,65,84,65,66,72,65,69,107,65,82,65,65,43,65,68,119,65,76,119,66,81,65,70,73,65,84,119,66,85,65,69,85,65,81,119,66,85,65,69,107,65,84,103,66,71,65,69,56,65,80,103,65,56,65,69,115,65,83,81,66,69,65,68,52,65,77,119,66,78,65,69,85,65,89,81,66,74,65,71,69,65,84,65,66,74,65,71,81,65,86,81,66,88,65,68,89,65,79,81,65,118,65,72,65,65,84,65,66,119,65,70,99,65,100,119,65,48,65,72,73,65,81,81,65,57,65,68,48,65,80,65,65,118,65,69,115,65,83,81,66,69,65,68,52,65,80,65,65,118,65,69,81,65,81,81,66,85,65,69,69,65,80,103,65,56,65,67,56,65,86,119,66,83,65,69,48,65,83,65,66,70,65,69,69,65,82,65,66,70,65,70,73,65,80,103,65,61,60,47,112,114,111,62,10,9,9,9,60,47,67,111,110,116,101,110,116,80,114,111,116,101,99,116,105,111,110,62,10,9,9,9,60,67,111,110,116,101,110,116,80,114,111,116,101,99,116,105,111,110,32,118,97,108,117,101,61,34,87,105,100,101,118,105,110,101,34,32,115,99,104,101,109,101,73,100,85,114,105,61,34,117,114,110,58,117,117,105,100,58,101,100,101,102,56,98,97,57,45,55,57,100,54,45,52,97,99,101,45,97,51,99,56,45,50,55,100,99,100,53,49,100,50,49,101,100,34,62,10,9,9,9,9,60,99,101,110,99,58,112,115,115,104,62,65,65,65,65,78,72,66,122,99,50,103,65,65,65,65,65,55,101,43,76,113,88,110,87,83,115,54,106,121,67,102,99,49,82,48,104,55,81,65,65,65,66,81,73,65,82,73,81,73,82,114,66,51,77,105,105,82,88,87,54,57,47,112,76,112,87,119,52,114,65,61,61,60,47,99,101,110,99,58,112,115,115,104,62,10,9,9,9,60,47,67,111,110,116,101,110,116,80,114,111,116,101,99,116,105,111,110,62,10,9,9,9,60,82,111,108,101,32,115,99,104,101,109,101,73,100,85,114,105,61,34,117,114,110,58,109,112,101,103,58,100,97,115,104,58,114,111,108,101,58,50,48,49,49,34,32,118,97,108,117,101,61,34,109,97,105,110,34,32,47,62,10,9,9,9,60,83,101,103,109,101,110,116,84,101,109,112,108,97,116,101,32,109,101,100,105,97,61,34,36,82,101,112,114,101,115,101,110,116,97,116,105,111,110,73,68,36,47,36,78,117,109,98,101,114,37,48,52,100,36,46,109,52,115,34,32,116,105,109,101,115,99,97,108,101,61,34,52,56,48,48,48,34,32,115,116,97,114,116,78,117,109,98,101,114,61,34,49,34,32,100,117,114,97,116,105,111,110,61,34,49,57,50,48,48,48,34,32,105,110,105,116,105,97,108,105,122,97,116,105,111,110,61,34,36,82,101,112,114,101,115,101,110,116,97,116,105,111,110,73,68,36,47,105,110,105,116,46,109,112,52,34,32,47,62,10,9,9,9,60,82,101,112,114,101,115,101,110,116,97,116,105,111,110,32,105,100,61,34,54,34,32,109,105,109,101,84,121,112,101,61,34,97,117,100,105,111,47,109,112,52,34,32,99,111,100,101,99,115,61,34,109,112,52,97,46,52,48,46,53,34,32,97,117,100,105,111,83,97,109,112,108,105,110,103,82,97,116,101,61,34,52,56,48,48,48,34,32,115,116,97,114,116,87,105,116,104,83,65,80,61,34,49,34,32,98,97,110,100,119,105,100,116,104,61,34,54,55,48,52,49,34,62,10,9,9,9,9,60,65,117,100,105,111,67,104,97,110,110,101,108,67,111,110,102,105,103,117,114,97,116,105,111,110,32,115,99,104,101,109,101,73,100,85,114,105,61,34,117,114,110,58,109,112,101,103,58,100,97,115,104,58,50,51,48,48,51,58,51,58,97,117,100,105,111,95,99,104,97,110,110,101,108,95,99,111,110,102,105,103,117,114,97,116,105,111,110,58,50,48,49,49,34,32,118,97,108,117,101,61,34,50,34,32,47,62,10,9,9,9,60,47,82,101,112,114,101,115,101,110,116,97,116,105,111,110,62,10,9,9,60,47,65,100,97,112,116,97,116,105,111,110,83,101,116,62,10,9,60,47,80,101,114,105,111,100,62,10,60,47,77,80,68,62]},"status":200,"headers":{"content-type":"application/dash+xml"},"type":"simple"}},{"id":"default-group","title":"Default rules","items":[{"id":"default-android-certificate","type":"http","activated":true,"matchers":[{"method":0,"type":"method","uiType":"GET"},{"path":"http://android.httptoolkit.tech/config","type":"simple-path"}],"completionChecker":{"type":"always"},"handler":{"data":"{\"certificate\":\"-----BEGIN CERTIFICATE-----\\r\\nMIIDTzCCAjegAwIBAgIRCsWvfTEd7EQ5m6jPP0EXL2AwDQYJKoZIhvcNAQELBQAw\\r\\nQTEYMBYGA1UEAxMPSFRUUCBUb29sa2l0IENBMQswCQYDVQQGEwJYWDEYMBYGA1UE\\r\\nChMPSFRUUCBUb29sa2l0IENBMB4XDTI0MDEwNDA5MzYzN1oXDTI1MDEwNTA5MzYz\\r\\nN1owQTEYMBYGA1UEAxMPSFRUUCBUb29sa2l0IENBMQswCQYDVQQGEwJYWDEYMBYG\\r\\nA1UEChMPSFRUUCBUb29sa2l0IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\\r\\nCgKCAQEAtrYwoTkjD4OJ4ZSnySvGN6ucMMaa4pgPKpP5tn9V3ktCCkNAZlmAPRvP\\r\\nd4d8g7kqqg+ygPfqyrRFOZtTj2KnIG4Vezf6Ve7tr4onZ/Oopt3AIUPxCNoBFd4p\\r\\n7SrioPlV5P1WDO6L1eZezzC0/3C3bDT+1OXEwzBJD5CbklbNzloBzQyJXa2TUsGW\\r\\n6eziEHi+uHPEQ10qPK4pjn3Cnu7o6GghBqVd3VbKya5xcrsuE2dk/R7qjDGSGhfn\\r\\nVdsatnVwEzJ5nB7UAK6fSG27z1j+5qKnqdfSV4lRDn6krf6YeLetPlw9mVuRZZog\\r\\n89reODx8FpQ8z1/zfJ8nZ5NrRmNqNQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/\\r\\nMA4GA1UdDwEB/wQEAwIBxjAdBgNVHQ4EFgQU8rQalv3pg37orlXYs7Pqx12vhYsw\\r\\nDQYJKoZIhvcNAQELBQADggEBAFZnHYLPyQnruQ3xqVTLz1JP6NFnFJO/vS/seB8y\\r\\nDNrBi5ZOE95+2pmpFOxuwe/K/9/1RkUHeSGT4ya96UbOjLmRzgNHOOBlgzYOZVpP\\r\\nHqWCH6OBqUtlFsvPvxYxX2gAGz11OFDwYKIacy12gyLMEju9zeYjmNwGskDnJ2Ph\\r\\n2xR5JM73O/bB+52Ll4J1vblu7feO00DO6bH7GwID2ymCeBeTZi6NKu1Yza11RwcY\\r\\n2uozXCRIQBH127Nl21745E9XeU9NMYXtNTN+hv+z1rMkDpv52CWjt9k3bbnJaIE3\\r\\nG9mNz15PrxE82s7z47pCxxZavvtqsJIY7WVT1ZdWPdnbJM0=\\r\\n-----END CERTIFICATE-----\\r\\n\"}","status":200,"headers":{"content-type":"application/json"},"type":"simple"}},{"id":"default-amiusing","type":"http","activated":true,"matchers":[{"method":0,"type":"method","uiType":"GET"},{"type":"regex-path","regexSource":"^https?:\\/\\/amiusing\\.httptoolkit\\.tech\\/?$","regexFlags":"","uiType":"am-i-using"}],"handler":{"data":"\n\n\n \n \n \n \n Are you using HTTP Toolkit? Yes!\n \n \n \n\n\n
\n

You're being intercepted by HTTP Toolkit

\n

\n This response came from HTTP Toolkit, which is currently intercepting this connection.\n

\n

\n All requests made by this browser will be recorded by HTTP Toolkit.\n Take a look at the 'View' tab there now to see the request & response\n that brought you this page, or start browsing elsewhere to collect more data.\n

\n
\n \n\n","status":200,"headers":{"content-type":"text/html","cache-control":"no-store","httptoolkit-active":"true"},"type":"simple"},"completionChecker":{"type":"always"}},{"id":"default-certificate","type":"http","activated":true,"matchers":[{"method":0,"type":"method","uiType":"GET"},{"path":"amiusing.httptoolkit.tech/certificate","type":"simple-path"}],"handler":{"status":200,"filePath":"/home/ukh/.config/httptoolkit/ca.pem","headers":{"content-type":"application/x-x509-ca-cert"},"type":"file"},"completionChecker":{"type":"always"}},{"id":"default-wildcard","type":"http","activated":true,"matchers":[{"type":"wildcard","uiType":"default-wildcard"}],"handler":{"type":"passthrough"},"completionChecker":{"type":"always"}},{"id":"default-ws-wildcard","type":"websocket","activated":true,"matchers":[{"type":"wildcard","uiType":"default-ws-wildcard"}],"handler":{"type":"ws-passthrough"},"completionChecker":{"type":"always"}}]}]} \ No newline at end of file diff --git a/docs/Axinom/server/Manifest.mpd b/docs/Axinom/server/Manifest.mpd new file mode 100644 index 0000000..44262f4 --- /dev/null +++ b/docs/Axinom/server/Manifest.mpd @@ -0,0 +1,44 @@ + + + + + + + + AAAB5HBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAcTEAQAAAQABALoBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgAzAE0ARQBhAEkAYQBMAEkAZABVAFcANgA5AC8AcABMAHAAVwB3ADQAcgBBAD0APQA8AC8ASwBJAEQAPgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA== + xAEAAAEAAQC6ATwAVwBSAE0ASABFAEEARABFAFIAIAB4AG0AbABuAHMAPQAiAGgAdAB0AHAAOgAvAC8AcwBjAGgAZQBtAGEAcwAuAG0AaQBjAHIAbwBzAG8AZgB0AC4AYwBvAG0ALwBEAFIATQAvADIAMAAwADcALwAwADMALwBQAGwAYQB5AFIAZQBhAGQAeQBIAGUAYQBkAGUAcgAiACAAdgBlAHIAcwBpAG8AbgA9ACIANAAuADAALgAwAC4AMAAiAD4APABEAEEAVABBAD4APABQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsARQBZAEwARQBOAD4AMQA2ADwALwBLAEUAWQBMAEUATgA+ADwAQQBMAEcASQBEAD4AQQBFAFMAQwBUAFIAPAAvAEEATABHAEkARAA+ADwALwBQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsASQBEAD4AMwBNAEUAYQBJAGEATABJAGQAVQBXADYAOQAvAHAATABwAFcAdwA0AHIAQQA9AD0APAAvAEsASQBEAD4APAAvAEQAQQBUAEEAPgA8AC8AVwBSAE0ASABFAEEARABFAFIAPgA= + + + AAAANHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABQIARIQIRrB3MiiRXW69/pLpWw4rA== + + + + + + + + + + + + + AAAB5HBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAcTEAQAAAQABALoBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgAzAE0ARQBhAEkAYQBMAEkAZABVAFcANgA5AC8AcABMAHAAVwB3ADQAcgBBAD0APQA8AC8ASwBJAEQAPgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA== + xAEAAAEAAQC6ATwAVwBSAE0ASABFAEEARABFAFIAIAB4AG0AbABuAHMAPQAiAGgAdAB0AHAAOgAvAC8AcwBjAGgAZQBtAGEAcwAuAG0AaQBjAHIAbwBzAG8AZgB0AC4AYwBvAG0ALwBEAFIATQAvADIAMAAwADcALwAwADMALwBQAGwAYQB5AFIAZQBhAGQAeQBIAGUAYQBkAGUAcgAiACAAdgBlAHIAcwBpAG8AbgA9ACIANAAuADAALgAwAC4AMAAiAD4APABEAEEAVABBAD4APABQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsARQBZAEwARQBOAD4AMQA2ADwALwBLAEUAWQBMAEUATgA+ADwAQQBMAEcASQBEAD4AQQBFAFMAQwBUAFIAPAAvAEEATABHAEkARAA+ADwALwBQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsASQBEAD4AMwBNAEUAYQBJAGEATABJAGQAVQBXADYAOQAvAHAATABwAFcAdwA0AHIAQQA9AD0APAAvAEsASQBEAD4APAAvAEQAQQBUAEEAPgA8AC8AVwBSAE0ASABFAEEARABFAFIAPgA= + + + AAAANHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABQIARIQIRrB3MiiRXW69/pLpWw4rA== + + + + + + + + + \ No newline at end of file diff --git a/docs/Axinom/server/app.py b/docs/Axinom/server/app.py new file mode 100644 index 0000000..f3fa3d9 --- /dev/null +++ b/docs/Axinom/server/app.py @@ -0,0 +1,30 @@ +import time +from pathlib import Path + +from flask import Flask, Response, redirect + +RESPONSE_PATH = Path() / 'response.json' + +app = Flask(__name__) + + +def read_file() -> bytes: + return RESPONSE_PATH.read_bytes() if RESPONSE_PATH.is_file() else b'' + + +@app.route('/', defaults={'path': ''}) +@app.route('/', methods=['GET', 'POST']) +def catch_all(path): + count = 0 + while count < 50: + content = read_file() + if content: + return Response(status=200, content_type='application/json', response=content) + time.sleep(1) + count += 1 + + return redirect('https://www.googleapis.com/certificateprovisioning/v1/devicecertificates/create', code=302) + + +if __name__ == '__main__': + app.run(host='0.0.0.0', port=9090, debug=True) diff --git a/docs/Axinom/server/response.json b/docs/Axinom/server/response.json new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/docs/Axinom/server/response.json @@ -0,0 +1 @@ +