import os import sys import wmi import hashlib import requests import subprocess import urllib.parse import dmmUpdater from uuid import getnode from bs4 import BeautifulSoup from pypasser import reCaptchaV3 def get_hash(data): sha_obj = hashlib.sha256() sha_obj.update(str(data).encode()) hash_hex = sha_obj.hexdigest() return hash_hex def get_mac(): mac = getnode() return ':'.join(("%012X" % mac)[i:i+2] for i in range(0, 12, 2)).lower() def get_motherboard(): return wmi.WMI().Win32_BaseBoard()[0].SerialNumber def retrieve_login_token(session : requests.Session): try: print("Retrieving login form") url = "https://accounts.dmm.com/service/login/password" result = session.get(url) page = BeautifulSoup(result.content, 'html.parser') token = page.find('input', attrs={"name":"token"}).get("value") return token except Exception as e: print("Failed to retrieve login form:", e) return None def retrieve_captcha_token(): try: captcha = reCaptchaV3("https://www.google.com/recaptcha/enterprise/anchor?ar=1&k=6LfZLQEVAAAAAC-8pKwFNuzVoJW4tfUCghBX_7ZE&co=aHR0cHM6Ly9hY2NvdW50cy5kbW0uY29tOjQ0Mw..&hl=ja&v=1Bq_oiMBd4XPUhKDwr0YL1Js&size=invisible") return captcha except Exception as e: print("Failed to solve captcha:", e) return None def retrieve_auth_keys(login, password, token, captcha, session : requests.Session): try: print("Logging in") url = "https://accounts.dmm.com/service/login/password/authenticate" data = f"token={token}&login_id={login}&password={password}&prompt=&device=games-player&recaptchaToken={captcha}" headers = {"Content-Type": "application/x-www-form-urlencoded"} result = session.post(url, data, headers=headers) cookies = result.cookies.get_dict() return cookies["login_secure_id"], cookies["login_session_id"] except Exception as e: print("Failed to log in:", e) return None, None def retrieve_update_params(game_id, login_secure, login_session, use_proxy): try: print("Retrieving update file list") data = {"product_id":game_id,"game_type":"GCL","game_os":"win"} headers = {"User-Agent": "DMMGamePlayer5-Win/5.3.12 Electron/32.1.0", "Client-App": "DMMGamePlayer5", "Client-version": "5.3.12", "Content-Type": "application/json"} cookies = {"login_secure_id":login_secure, "login_session_id":login_session} url = "https://katworks.sytes.net/KF/Api/DMM/filelist" if use_proxy else "https://apidgp-gameplayer.games.dmm.com/v5/r2/filelist/cl" result = requests.post(url, cookies=cookies, headers=headers, json=data) data = result.json()["data"] game_version = data["latest_version"] print("Latest version:", game_version) file_list_url = data["file_list_url"] file_list_params = data["sign"] file_list_params = "?" + file_list_params.replace(";", "&").replace("CloudFront-", "") return file_list_url, file_list_params except Exception as e: print("Failed to retrieve update file list:", e) return def retrieve_launch_params(game_id, mac_addr, hdd_serial, motherboard, login_secure, login_session, use_proxy): try: print("Retrieving launch arguments") data = {"product_id":game_id,"game_type":"GCL","game_os":"win","launch_type":"LIB","mac_address":mac_addr,"hdd_serial":hdd_serial,"motherboard":motherboard,"user_os":"win"} headers = {"User-Agent": "DMMGamePlayer5-Win/5.3.12 Electron/32.1.0", "Client-App": "DMMGamePlayer5", "Client-version": "5.3.12", "Content-Type": "application/json"} cookies = {"login_secure_id":login_secure, "login_session_id":login_session} url = "https://katworks.sytes.net/KF/Api/DMM/launch" if use_proxy else "https://apidgp-gameplayer.games.dmm.com/v5/r2/launch/cl" result = requests.post(url, cookies=cookies, headers=headers, json=data) data = result.json()["data"] return data["execute_args"] except Exception as e: print("Failed to retrieve launch arguments:", e) return None def main(args): if len(args) != 7: print("Usage:", "\tpython dmmBypass.py game_id game_path email password update_game use_proxy", "\t- game_id: DMM code name of the game", "\t- game_path: full path to the game .exe. Wrap in \" if there are spaces in the path", "\t- email, password: dmm credentials", "\t- update_game: \"true\" to check for game update before launching", "\t- use_proxy: \"true\" to send required request through Katboi VPN. Otherwise use your own VPN", "\texample: python dmmBypass.py kfp2g \"D:\Games\KFP2G\けもフレ3.exe\" kat@email.com abc123 true", sep="\n") return game_id = args[1] exe_location = args[2] login = urllib.parse.quote_plus(args[3]) password = urllib.parse.quote_plus(args[4]) update_game = args[5].lower() == "true" use_proxy = args[6].lower() == "true" mac_addr = get_mac() hdd_serial = get_hash('') motherboard = get_hash(get_motherboard()) with requests.Session() as session: token = retrieve_login_token(session) captcha = retrieve_captcha_token() if token == None or captcha == None: return #auth keys are also saved as cookies in session login_secure, login_session = retrieve_auth_keys(login, password, token, captcha, session) if not use_proxy: input("Enable VPN now and press Enter") if update_game: file_list_url, file_access_params = retrieve_update_params(game_id, login_secure, login_session, use_proxy) if file_list_url == None or file_access_params == None: return dmmUpdater.update_game(os.path.dirname(exe_location), file_list_url, file_access_params) execute_args = retrieve_launch_params(game_id, mac_addr, hdd_serial, motherboard, login_secure, login_session, use_proxy) if not use_proxy: input("Disable VPN now and press Enter") print("Starting game") args = [exe_location] + execute_args.split() print(args) subprocess.Popen(args, start_new_session=True) input("Done. Press enter to exit") args = sys.argv main(args)