Skip to content

Commit 7365b0d

Browse files
committed
feat(docker): Try to add some 3DS setup stuff
1 parent 4b599df commit 7365b0d

2 files changed

Lines changed: 77 additions & 0 deletions

File tree

.docker/hybrid-account.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
from urllib.parse import parse_qsl
2+
from base64 import b64decode, b64encode
3+
from hashlib import sha256
4+
import bcrypt
5+
import json
6+
7+
request = input("NASC request blob:")
8+
9+
parts = parse_qsl(request)
10+
11+
def decode_base64(enc: str):
12+
enc = enc.replace('.', '+').replace('-', '/').replace('*', '=')
13+
return b64decode(enc)
14+
parts = dict(((key, decode_base64(val)) for key, val in parts))
15+
16+
pid = int(parts['userid'].decode('ascii'))
17+
fcdcert_hash = sha256(parts['fcdcert']).digest()
18+
19+
print("OK.")
20+
password = input(f"NEX Password for {pid}:")
21+
fc = input("FC (XXXX-XXXX-XXXX):")
22+
pnidpid = int(input("PNID PID:"))
23+
pnidpassword = input("PNID password:")
24+
25+
def nintendo_password(password: str, pid: int):
26+
buf = pid.to_bytes(4, 'little')
27+
buf += b'\x02\x65\x43\x46'
28+
buf += password.encode('ascii')
29+
return sha256(buf).digest().hex()
30+
31+
print(json.dumps({
32+
'device_type': '3ds',
33+
'access_level': 0,
34+
'server_access_level': "prod",
35+
'pid': pid,
36+
'password': password,
37+
'friend_code': fc,
38+
}))
39+
40+
print(json.dumps({
41+
'model': "ctr",
42+
'serial': parts['csnum'].decode('ascii'),
43+
'access_level': 0,
44+
'server_access_level': 'prod',
45+
'certificate_hash': b64encode(fcdcert_hash).decode('ascii'),
46+
'fcdcert_hash': b64encode(fcdcert_hash).decode('ascii'),
47+
'device_attributes': [],
48+
}))
49+
50+
pwhash = nintendo_password(pnidpassword, pnidpid)
51+
bpwsalt = bcrypt.gensalt(10)
52+
bpwhash = bcrypt.hashpw(pwhash.encode('ascii'), bpwsalt)
53+
print(f"{pnidpid}: {bpwhash.decode('ascii')}")

.docker/hyrbid-accounts.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
For 3DS testing, "hybrid accounts" are often needed. This is where the same account information is accepted on both
2+
prod and local servers. If you see 002-0102 on the proxy, this is likely the issue.
3+
4+
You need:
5+
- Any NASC request blob (copy this from mitmproxy). Starts with "gameid="...
6+
- Your NEX password (https://9net.org/~stary/get_3ds_pid_password.3dsx)
7+
- Your 3DS friend code (you can click past the ban message to see this)
8+
- The PID for your linked PNID (https://pnidlt.gab.net.eu.org/)
9+
- The password for your linked PNID
10+
11+
First, register a PNID with the same username as your linked PNID. The password will be overwritten later.
12+
```shell
13+
# REGISTER
14+
https_proxy=http://localhost:8888 curl -k -v -X POST -H "Content-Type: application/json" --data '{"email":"ash@heyquark.com", "username":"PN_quarky", "mii_name":"Luca", "password":"letm3in", "password_confirm":"letm3in"}' https://api.pretendo.cc/v1/register/
15+
```
16+
17+
Then, run `hybrid-account.py` and provide the information it asks for. It will give:
18+
- A `nexaccounts` record (JSON, `device_type`, `access_level`...)
19+
- A `devices` record (JSON, `model`, `serial`...)
20+
- The PNID PID and hashed password
21+
22+
Your best bet is to insert these into the database using MongoDB Compass. Connect to `localhost` then in `account/nexaccounts`, Add Data->Insert Document, paste the output from the script. Same for `account/devices`.
23+
24+
Locate your newly-registered PNID in `account/pnids` and overwrite the `pid` and `password` fields with the values provided by the script.

0 commit comments

Comments
 (0)