Added trust levels for the public VPN

This commit is contained in:
katboi01 2025-03-11 00:36:06 +01:00
parent 92e46a56f5
commit 06b4bca63a
2 changed files with 31 additions and 18 deletions

View File

@ -2,9 +2,10 @@
Efficient KF3/DMM game launcher.
## Requirements
Python 3 and pip.
- Python 3 and pip.
- DMM account that owns KF3
KF3 installed from DMM. DMM itself does not need to be running.
KF3 installed from DMM is recommended but not required.
## Instructions
Download the files from this repo. Unzip them to a safe place.
@ -13,11 +14,16 @@ Run `run_KF3.bat`, it will ask you for some information.
It will ask for the location of the KF3 executable. Generally this will be `C:\users\[your name]\KFP2G\けもフレ3.exe`.
Input your DMM email and then password when prompted, and `yes` if you want to use the public VPN to connect to DMM's server. If you choose not to use the public VPN, then you will need to enable your own Japanese VPN while logging in to the game.
Input your DMM email and then password when prompted, and set the desired trust level (more info on that below). If you choose not to use the public VPN, then you will need to enable your own Japanese VPN while logging in to the game.
If you make a mistake or you want to change login details, edit the `kfp2g.cfg` config file, or delete it to run the configuration again.
If KF3 needs to update, use `update_and_run_KF3.bat` and it will install any new updates.
## Known issues
Retrieving launch arguments - error 308: Every once in a while, DMM games may have updated terms of service that need to be accepted. This can only be done via the official DMM app.
## Trust levels
DMM uses Geo-blocking for some requests, that requires the user to be in Japan. This can be bypassed with a VPN. I have access to an OpenVPN server owned by HAV0X that can be used to bypass this restriction. However, this comes with several security vulnerabilities for the user:
- trust level 2 - Your login and password are sent to my device. The request is processed and sent through the VPN to DMM server, and my device sends you the response. I could access the information sent in the request if I wanted to (I will not do that though).
- trust level 1 - My device is used as a proxy. A connection is made between your device, my device, and DMM, with no way of me viewing the request data (that I know of). This takes longer.
- trust level 0 - You use your own VPN. The launcher will prompt you to enable/disable VPN when needed.
I do not intentionally view or store any data sent through my server. There is no guarantee of my and HAV0X's proxy server being active at any given time.

View File

@ -32,8 +32,16 @@ if not os.path.exists(config_name):
"file_path" : input('Enter full file path to KF3 .exe: ').strip('\"'),
"dmm_login" : input('DMM Login (email): '),
"dmm_password" : input('DMM Password: '),
"use_proxy" : input('Your login tokens will be sent through my VPN machine.\nIs that okay? (yes/no): ').lower() == "yes"
}
while True:
try:
trust_level = int(input('\t0 - Use your own VPN\n\t1 - Use Katboi\'s VPN as a proxy (slower, more secure)\n\t2 - Use Katboi\'s VPN to process the request (fastest, unsecure)\nTrust level (0-2): '))
if trust_level < 0 or trust_level > 2: raise Exception()
config["trust_level"] = trust_level
break
except:
print("Value must be in 0-2 range")
save_config(config_name, config)
else:
config = load_config(config_name)
@ -104,11 +112,11 @@ def retrieve_auth_keys(login, password, token, captcha, session : requests.Sessi
print("Failed to log in:", e)
return None, None
def agree_to_game_terms(game_id, use_proxy):
def agree_to_game_terms(game_id, trust_level):
try:
print("Accepting updated game terms of use")
headers = {"User-Agent": "DMMGamePlayer5-Win/5.3.12 Electron/32.1.0", "Client-App": "DMMGamePlayer5", "Client-version": "5.3.12", "Content-Type": "application/json"}
url = "" if use_proxy else "https://apidgp-gameplayer.games.dmm.com/v5/agreement/confirm/client"
url = "https://katworks.sytes.net/KF/Api/DMM/agreement" if trust_level == 2 else "https://katworks.sytes.net/proxy/agreement" if trust_level == 1 else "https://apidgp-gameplayer.games.dmm.com/v5/agreement/confirm/client"
data = {"product_id":game_id,"is_notification":False,"is_myapp":False}
result = requests.post(url, headers=headers, json=data)
result.raise_for_status()
@ -120,21 +128,21 @@ def agree_to_game_terms(game_id, use_proxy):
print("Failed to accept terms of use:", e)
return False
def retrieve_launch_params(game_id, game_type, mac_addr, hdd_serial, motherboard, login_secure, login_session, use_proxy, update_game):
def retrieve_launch_params(game_id, game_type, mac_addr, hdd_serial, motherboard, login_secure, login_session, trust_level, update_game):
try:
print("Retrieving launch arguments")
data = {"product_id":game_id,"game_type":game_type,"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}
if update_game:
url = "https://katworks.sytes.net/KF/Api/DMM/update" if use_proxy else "https://apidgp-gameplayer.games.dmm.com/v5/r2/launch/cl"
url = "https://katworks.sytes.net/KF/Api/DMM/update" if trust_level == 2 else "https://katworks.sytes.net/proxy/launchAndUpdate" if trust_level == 1 else "https://apidgp-gameplayer.games.dmm.com/v5/r2/launch/cl"
else:
url = "https://katworks.sytes.net/KF/Api/DMM/launch" if use_proxy else "https://apidgp-gameplayer.games.dmm.com/v5/launch/cl"
url = "https://katworks.sytes.net/KF/Api/DMM/launch" if trust_level == 2 else "https://katworks.sytes.net/proxy/launch" if trust_level == 1 else "https://apidgp-gameplayer.games.dmm.com/v5/launch/cl"
result = requests.post(url, cookies=cookies, headers=headers, json=data)
result.raise_for_status()
result_json = result.json()
if result_json["result_code"] == 308:
if agree_to_game_terms(game_id, use_proxy):
if agree_to_game_terms(game_id, trust_level):
result = requests.post(url, cookies=cookies, headers=headers, json=data)
result.raise_for_status()
result_json = result.json()
@ -158,7 +166,7 @@ def main(config):
password = urllib.parse.quote_plus(config["dmm_password"])
#optional arguments
update_game = config.get("update_game", False)
use_proxy = config.get("use_proxy", False)
trust_level = config.get("trust_level", 0)
saved_login = config.get("saved_login", None)
#dmm requires these values
mac_addr = get_mac()
@ -193,10 +201,10 @@ def main(config):
del(config["update_game"])
save_config(config_name, config)
if not use_proxy: input("Enable VPN now and press Enter")
if trust_level == 0: input("Enable VPN now and press Enter")
#execute_args, file_list_url, file_access_params
launch_data : dict = retrieve_launch_params(game_id, game_type, mac_addr, hdd_serial, motherboard, login_secure, login_session, use_proxy, update_game)
launch_data : dict = retrieve_launch_params(game_id, game_type, mac_addr, hdd_serial, motherboard, login_secure, login_session, trust_level, update_game)
execute_args : str = launch_data.get("execute_args", None)
if execute_args == None:
@ -215,15 +223,14 @@ def main(config):
install_dir = launch_data["install_dir"]
game_root_path = get_game_root_path(exe_location, install_dir, exec_name)
if not use_proxy: input("Disable VPN now and press Enter")
if trust_level == 0: input("Disable VPN now and press Enter")
if update_game:
dmmUpdater.update_game(game_root_path, file_list_url, file_list_params)
print("Starting game")
args = [os.path.join(game_root_path, exec_name)] + execute_args.split()
print(args)
subprocess.Popen(args, start_new_session=True)
input("Done. Press enter to exit (this will close the game)")
input("Done. Press enter to exit")
main(config)