import os import sys import wmi import json import hashlib import requests import dmmUpdater import subprocess import urllib.parse from uuid import getnode from bs4 import BeautifulSoup from pypasser import reCaptchaV3 def print_request(url, data : str, headers, cookies_dict): print("Sending to", url) vars = {"headers":headers, "cookies":cookies_dict, "data":data} print(json.dumps(vars, ensure_ascii=False, indent=1)) pass 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" print_request(url, "", dict(session.headers), session.cookies.get_dict()) result = session.get(url) print(result.status_code, result.text) result.raise_for_status() 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) 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) 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"} print_request(url, data, headers, session.cookies.get_dict()) result = session.post(url, data, headers=headers) print(result.status_code, result.text) result.raise_for_status() cookies = result.cookies.get_dict() return cookies["login_secure_id"], cookies["login_session_id"] except Exception as e: print("Failed to log in:", e) 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" print_request(url, data, headers, cookies) result = requests.post(url, cookies=cookies, headers=headers, json=data) print(result.status_code, result.text) result.raise_for_status() 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) 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" print_request(url, data, headers, cookies) result = requests.post(url, cookies=cookies, headers=headers, json=data) print(result.status_code, result.text) result.raise_for_status() data = result.json()["data"] return data["execute_args"] except Exception as e: print("Failed to retrieve launch arguments:", e) 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 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 execute_args = retrieve_launch_params(game_id, mac_addr, hdd_serial, motherboard, login_secure, login_session, use_proxy) if execute_args == None: return if not use_proxy: input("Disable VPN now and press Enter") if update_game: dmmUpdater.update_game(os.path.dirname(exe_location), file_list_url, file_access_params) 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)