Created
July 18, 2025 21:44
-
-
Save Ap0dexMe0/d7f68a4f406eec5dce2d47f81a2019a5 to your computer and use it in GitHub Desktop.
Cryptography, Encoding & Obfuscation Analyzer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import base64 | |
| import binascii | |
| import re | |
| import urllib.parse | |
| import codecs | |
| import math | |
| import html | |
| import quopri | |
| import string | |
| class DETECTION: | |
| def __init__(self): | |
| self.findings = [] | |
| def analyze(self, data: str) -> list: | |
| self.findings = [] | |
| # ==== ENCODING ==== | |
| self._check_base64(data) | |
| self._check_base32(data) | |
| self._check_base16(data) | |
| self._check_base58(data) | |
| self._check_base85(data) | |
| self._check_ascii85(data) | |
| self._check_hex(data) | |
| self._check_url_encoding(data) | |
| self._check_html_entities(data) | |
| self._check_quoted_printable(data) | |
| self._check_uuencode(data) | |
| self._check_morse_code(data) | |
| # ==== ENCRYPTION (heuristic) ==== | |
| self._check_entropy(data) | |
| self._check_openssl(data) | |
| self._check_pem_blocks(data) | |
| self._check_jwt(data) | |
| self._check_fernet(data) | |
| self._check_zip(data) | |
| self._check_pdf(data) | |
| self._check_ms_office(data) | |
| # ==== OBFUSCATION ==== | |
| self._check_rot13(data) | |
| self._check_rot47(data) | |
| self._check_xor(data) | |
| self._check_reversed(data) | |
| self._check_eval_patterns(data) | |
| self._check_double_base64(data) | |
| self._check_unicode_escape(data) | |
| self._check_jsfuck(data) | |
| self._check_emoji_obfuscation(data) | |
| # ==== HASH TYPE ==== | |
| self._check_hash_type(data) | |
| return list(set(self.findings)) | |
| # === ENCODING DETECTION === | |
| def _check_base64(self, data): | |
| try: | |
| base64.b64decode(data, validate=True) | |
| self.findings.append("Base64") | |
| except: pass | |
| def _check_base32(self, data): | |
| try: | |
| base64.b32decode(data) | |
| self.findings.append("Base32") | |
| except: pass | |
| def _check_base16(self, data): | |
| try: | |
| base64.b16decode(data.upper()) | |
| self.findings.append("Base16") | |
| except: pass | |
| def _check_base58(self, data): | |
| if all(c in '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' for c in data): | |
| self.findings.append("Base58") | |
| def _check_base85(self, data): | |
| try: | |
| base64.b85decode(data) | |
| self.findings.append("Base85") | |
| except: pass | |
| def _check_ascii85(self, data): | |
| try: | |
| base64.a85decode(data) | |
| self.findings.append("ASCII85") | |
| except: pass | |
| def _check_hex(self, data): | |
| try: | |
| bytes.fromhex(data) | |
| self.findings.append("Hexadecimal") | |
| except: pass | |
| def _check_url_encoding(self, data): | |
| if urllib.parse.unquote(data) != data: | |
| self.findings.append("URL Encoded") | |
| def _check_html_entities(self, data): | |
| if html.unescape(data) != data: | |
| self.findings.append("HTML Entities") | |
| def _check_quoted_printable(self, data): | |
| try: | |
| if quopri.decodestring(data.encode()).decode(errors='ignore') != data: | |
| self.findings.append("Quoted-Printable") | |
| except: pass | |
| def _check_uuencode(self, data): | |
| if re.match(r'begin [0-7]{3} .+', data): | |
| self.findings.append("UUEncode") | |
| def _check_morse_code(self, data): | |
| if re.fullmatch(r'[\.\-\s]+', data.strip()): | |
| self.findings.append("Morse Code") | |
| # === ENCRYPTION DETECTION (Heuristics) === | |
| def _check_entropy(self, data): | |
| if len(data) < 16: | |
| return | |
| entropy = -sum((p := data.count(c) / len(data)) * math.log2(p) for c in set(data)) | |
| if entropy > 4.5: | |
| self.findings.append("High Entropy (Possibly Encrypted)") | |
| def _check_openssl(self, data): | |
| if data.startswith("Salted__"): | |
| self.findings.append("OpenSSL AES Encrypted") | |
| def _check_pem_blocks(self, data): | |
| if re.search(r'-----BEGIN (RSA|PGP|ENCRYPTED|CERTIFICATE)', data): | |
| self.findings.append("PEM Encrypted Block") | |
| def _check_jwt(self, data): | |
| parts = data.split(".") | |
| if len(parts) == 3: | |
| try: | |
| base64.urlsafe_b64decode(parts[1] + '==') | |
| self.findings.append("JWT Token") | |
| except: pass | |
| def _check_fernet(self, data): | |
| try: | |
| decoded = base64.urlsafe_b64decode(data + '==') | |
| if len(decoded) == 128: | |
| self.findings.append("Fernet Token") | |
| except: pass | |
| def _check_zip(self, data): | |
| if data.startswith("PK\x03\x04"): | |
| self.findings.append("Encrypted ZIP Archive") | |
| def _check_pdf(self, data): | |
| if "%PDF" in data and "/Encrypt" in data: | |
| self.findings.append("Encrypted PDF") | |
| def _check_ms_office(self, data): | |
| if data.startswith("\xd0\xcf\x11\xe0"): | |
| self.findings.append("MS Office Compound File (Possibly Encrypted)") | |
| # === OBFUSCATION DETECTION === | |
| def _check_rot13(self, data): | |
| try: | |
| if codecs.decode(data, 'rot_13') != data: | |
| self.findings.append("ROT13") | |
| except: pass | |
| def _check_rot47(self, data): | |
| decoded = ''.join( | |
| chr(33 + ((ord(c) - 33 + 47) % 94)) if 33 <= ord(c) <= 126 else c for c in data | |
| ) | |
| if decoded != data: | |
| self.findings.append("ROT47") | |
| def _check_xor(self, data): | |
| try: | |
| raw = bytes(data, 'utf-8') | |
| for key in range(1, 256): | |
| xor_result = bytes([b ^ key for b in raw]) | |
| ascii_ratio = sum([32 <= c < 127 for c in xor_result]) / len(xor_result) | |
| if ascii_ratio > 0.9: | |
| self.findings.append("XOR Obfuscation (Heuristic)") | |
| break | |
| except: pass | |
| def _check_reversed(self, data): | |
| if data[::-1].isprintable(): | |
| self.findings.append("Reversed String") | |
| def _check_eval_patterns(self, data): | |
| if "eval(" in data or "String.fromCharCode" in data: | |
| self.findings.append("JavaScript Obfuscation (eval/charCode)") | |
| def _check_double_base64(self, data): | |
| try: | |
| first = base64.b64decode(data) | |
| second = base64.b64decode(first) | |
| if second: | |
| self.findings.append("Double Base64") | |
| except: | |
| pass | |
| def _check_unicode_escape(self, data): | |
| if "\\u" in data: | |
| self.findings.append("Unicode Escaped") | |
| def _check_jsfuck(self, data): | |
| if all(c in '[]()+! ' for c in data.strip()) and len(data) > 10: | |
| self.findings.append("JSFuck (Obfuscated JS)") | |
| def _check_emoji_obfuscation(self, data): | |
| emoji_pattern = re.compile("[" | |
| "\U0001F600-\U0001F64F" # emoticons | |
| "\U0001F300-\U0001F5FF" # symbols & pictographs | |
| "\U0001F680-\U0001F6FF" # transport & map | |
| "\U0001F1E0-\U0001F1FF" # flags | |
| "]+", flags=re.UNICODE) | |
| if emoji_pattern.search(data): | |
| self.findings.append("Emoji Obfuscation") | |
| def _check_hash_type(self, data): | |
| hash_patterns = { | |
| r'^[a-f0-9]{32}$': 'MD5', | |
| r'^[A-F0-9]{32}$': 'LM Hash', | |
| r'^[a-f0-9]{40}$': 'SHA1', | |
| r'^[a-f0-9]{56}$': 'SHA224', | |
| r'^[a-f0-9]{64}$': 'SHA256 / BLAKE2s', | |
| r'^[a-f0-9]{96}$': 'SHA384', | |
| r'^[a-f0-9]{128}$': 'SHA512 / BLAKE2b', | |
| r'^[A-F0-9]{16}$': 'Oracle 10g Hash', | |
| r'^[0-9a-f]{8}$': 'CRC32', | |
| r'^[0-9]{10}$': 'CRC32 (decimal)', | |
| r'^\$2[aby]\$.{56}$': 'bcrypt', | |
| r'^\$s0\$.*': 'scrypt', | |
| r'^\$pbkdf2-.+\$': 'PBKDF2', | |
| r'^\$argon2(id|i|d)\$.*': 'Argon2', | |
| r'^\$P\$.*': 'Wordpress MD5', | |
| r'^\$H\$.*': 'Drupal MD5', | |
| r'^\$S\$.*': 'Drupal SHA512', | |
| r'^\*[A-F0-9]{40}$': 'MySQL 5+ (SHA1)', | |
| r'^[A-F0-9]{16}$': 'MySQL Pre-4.1', | |
| } | |
| for pattern, name in hash_patterns.items(): | |
| if re.fullmatch(pattern, data): | |
| self.findings.append(f"Hash Type: {name}") | |
| break | |
| if __name__ == "__main__": | |
| detector = DETECTION() | |
| samples = [ | |
| "5f4dcc3b5aa765d61d8327deb882cf99", # MD5 | |
| "900150983cd24fb0d6963f7d28e17f72", # MD5 | |
| "5baa61e4c9b93f3f0682250b6cf8331b", # SHA1-like | |
| "2c1743a391305fbf367df8e4f069f9f9", # NTLM | |
| "$2a$12$EXRkfkdmXn2gzds2SSitu.", # bcrypt | |
| "$argon2id$v=19$m=65536,t=2,p=1$...", # Argon2 | |
| "U29tZVRleHQ=", # Base64 | |
| "68656c6c6f", # Hex | |
| "Uryyb Jbeyq!", # ROT13 | |
| "eval(String.fromCharCode(65))", # JS Obfuscation | |
| "PK\x03\x04", # ZIP Header | |
| "Salted__\x9a\xbc...", # OpenSSL | |
| "%68%65%6C%6C%6F", # URL | |
| "[+![]]", # JSFuck | |
| "πππ", # Emoji Obfuscation | |
| ] | |
| for s in samples: | |
| print(f"Input: {s}") | |
| print(f"Detected: {detector.analyze(s)}\n") | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment