Created
March 17, 2026 11:24
-
-
Save Baw-Appie/4e76daf98d9b1b1c7da4a1b474af1d90 to your computer and use it in GitHub Desktop.
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
| #!/usr/bin/env python3 | |
| """Test different decryption configurations for KakaoTalk database.""" | |
| # from pysqlcipher3 import dbapi2 as sqlite | |
| import hashlib | |
| import base64 | |
| from pathlib import Path | |
| import subprocess | |
| def get_device_uuid(): | |
| """Get the Mac's hardware UUID.""" | |
| result = subprocess.run( | |
| ["ioreg", "-d2", "-c", "IOPlatformExpertDevice"], | |
| capture_output=True, text=True | |
| ) | |
| for line in result.stdout.split('\n'): | |
| if 'IOPlatformUUID' in line: | |
| return line.split('"')[-2] | |
| raise Exception("Could not get device UUID") | |
| def pbkdf2(password: bytes, salt: bytes): | |
| return hashlib.pbkdf2_hmac("sha256", password, salt, 100000, 128) | |
| def hashedDeviceUUID(uuid: str): | |
| uuid_bytes = uuid.encode("ascii") | |
| return base64.b64encode( | |
| hashlib.sha1(uuid_bytes).digest() + hashlib.sha256(uuid_bytes).digest() | |
| ).decode("ascii") | |
| def getDatabaseName(userId: int, uuid: str): | |
| hawawa = ".".join([ | |
| ".", "F", str(userId), "A", "F", | |
| "".join(reversed(uuid)), ".", "|", | |
| ]) | |
| return pbkdf2( | |
| hawawa.encode("ascii"), | |
| "".join(reversed(hashedDeviceUUID(uuid))).encode("ascii") | |
| ).hex()[28:28+78] | |
| def getSecureKey(userId: int, uuid: str): | |
| hawawa = "F".join([ | |
| "A", hashedDeviceUUID(uuid), "|", "F", | |
| uuid[:5], "H", str(userId), "|", uuid[7:] | |
| ]) | |
| return pbkdf2( | |
| "".join(reversed(hawawa)).encode("ascii"), | |
| uuid[int(len(uuid) * 0.3):].encode("ascii") | |
| ).hex() | |
| def find_user_id_from_cache(): | |
| """Try to find user ID from cache database.""" | |
| import sqlite3 | |
| cache_path = Path.home() / "Library/Containers/com.kakao.KakaoTalkMac/Data/Library/Caches/Cache.db" | |
| if not cache_path.exists(): | |
| return None | |
| conn = sqlite3.connect(str(cache_path)) | |
| cursor = conn.cursor() | |
| cursor.execute("SELECT request_key FROM cfurl_cache_response WHERE request_key LIKE '%bzm-capi%'") | |
| for row in cursor.fetchall(): | |
| url = row[0] | |
| if '/client/' in url: | |
| parts = url.split('/client/') | |
| if len(parts) > 1: | |
| user_id = parts[1].split('/')[0] | |
| if user_id.isdigit(): | |
| conn.close() | |
| return int(user_id) | |
| conn.close() | |
| return None | |
| def find_database(): | |
| """Find the active KakaoTalk database.""" | |
| base_path = Path.home() / "Library/Containers/com.kakao.KakaoTalkMac/Data/Library/Application Support/com.kakao.KakaoTalkMac" | |
| # Find the largest database file (most likely active) | |
| db_files = [] | |
| for f in base_path.iterdir(): | |
| if f.is_file() and len(f.name) == 78: # Database name length | |
| db_files.append((f, f.stat().st_size)) | |
| if db_files: | |
| db_files.sort(key=lambda x: x[1], reverse=True) | |
| return db_files[0][0] | |
| return None | |
| def hashedDeviceUUID(uuid: str): | |
| uuid_bytes = uuid.encode("ascii") | |
| return base64.b64encode( | |
| hashlib.sha1(uuid_bytes).digest() + hashlib.sha256(uuid_bytes).digest() | |
| ).decode("ascii") | |
| def getSecureKey(userId: int, uuid: str): | |
| hawawa = "F".join([ | |
| "A", hashedDeviceUUID(uuid), "|", "F", | |
| uuid[:5], "H", str(userId), "|", uuid[7:] | |
| ]) | |
| return pbkdf2( | |
| "".join(reversed(hawawa)).encode("ascii"), | |
| uuid[int(len(uuid) * 0.3):].encode("ascii") | |
| ).hex() | |
| secure_key = getSecureKey(find_user_id_from_cache(), get_device_uuid()) | |
| print(f"Secure Key: {secure_key}") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment