Skip to content

Instantly share code, notes, and snippets.

@yifanlu
Last active November 3, 2023 22:55
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save yifanlu/e80db121d38aceb8cca0e03cefd5853b to your computer and use it in GitHub Desktop.
Save yifanlu/e80db121d38aceb8cca0e03cefd5853b to your computer and use it in GitHub Desktop.
3DS System Transfer + NNID & eShop on new region
This is an ADVANCED guide and should not be attempted by anyone who does not COMPLETELY understand each step and what it does to their device. Additionally, the prerequisite is that you have already performed a region change on your 3DS. You also need access to another 3DS on the target region that you can format to a non-NNID linked state (you can use emuNAND here). For simplicity, I am going to assume you are region changing a N3DS from Japan to USA and have access to a USD O3DS. The guide is in two parts: System Transfer and NNID Linking. For those who wish to just have access to USA eShop (and the ability to download free games; if you only want to use eShop to purchase games, you do not have to link a NNID) you can skip to the second part.
To modify requests, I use Charles Proxy to set breakpoints so I can change requests and responses as they come in. However, you can do it in any why you choose. Also, since 9.2 eShop was disabled, you may have to additionally modify all requests from the 3DS to send a different CVer in the headers of your requests. When I performed this, it was not necessary so YMMV)
Before starting:
1) Both O3DS and N3DS are on 9.2.0-20U
2) N3DS has been formatted after region swap and no NNID linked
3) N3DS has the CORRECT (original) serial in SecureInfo_A with the CHANGED (new) region (this means you have to patch the signature checks in cfg for SecureInfo_A! 3ds_injector has a patch for this)
Prerequisites:
1) Both O3DS and N3DS are on 9.2.0-20U
2) N3DS has been formatted after region swap and no NNID linked
O3DS code.bin patches needed: https://gist.github.com/yifanlu/b59b6d83d11bdb244cbd
System Transfer:
1) Create code.bin with your IP address, copy it to O3DS (Note since the release of 3ds_injector, you can port the required NIM patches to 3ds_injector or use the spider exploit with the code.bin. Your choice.)
2) Enter system transfer and start sending
3) On N3DS, enter NTR mode, enter the following commands <= this sets NIM to request from your forwarding server instead of Nintendo. That way the requests/responses can be modified
write(0x14e1bc,tuple(map(ord, "http://ip:8888/ECommerceSOAP\0")), pid=0x25)
write(0x14e533,tuple(map(ord, "http://ip:8888/ECommerceSOAP\0")), pid=0x25)
write(0x14e4f4,tuple(map(ord, "http://ip:8888/NetUpdateSOAP\0")), pid=0x25)
write(0xfffffd5,tuple(map(ord, "N3DS_SERIAL_HERE\0")),pid=0x7) <= change serial in cfg
write(0x0010DD28, (0x00, 0x20, 0x08, 0x60, 0x70, 0x47), pid=0x25) <= disable eshop update request
4) Enter system settings -> system transfer
5) (*) First response: ecs:GetAccountStatusResponse, patch the last couple of service urls:
<ServiceURLs><Name>EcsURL</Name><URI>http://ip:8888/ECommerceSOAP</URI></ServiceURLs><ServiceURLs><Name>IasURL</Name><URI>http://ip:8888/IdentityAuthenticationSOAP</URI></ServiceURLs><ServiceURLs><Name>CasURL</Name><URI>http://ip:8888/CatalogingSOAP</URI></ServiceURLs><ServiceURLs><Name>NusURL</Name><URI>http://ip:8888/NetUpdateSOAP</URI></ServiceURLs>
Also patch <Currency>USD</Currency></Balance><Country>US</Country><Region>USA</Region>
5a) If the next request is to ivs:GetChallenge, then run the following NTR command:
write(0x1febec,tuple(map(ord, "JP")),pid=0x25) <= Nintendo's servers will reject IVS requests where the CtCert does not match the Country in the request. Must be changed in code because the request is signed with CtCert.
5b) After the ivs:RegisterResponse response, it will make another ecs:GetAccountStatus request, make the same changes to the response as in (*)
5c) This may take a couple of tries; if it errors, enter system transfer and try again
6) Wait until: ivs:MoveAccountResponse, change ErrorCode response to <ErrorCode>0</ErrorCode> <= This is a dry run of what's in step 8
7) Go through system transfer... until step 5 in the system transfer process (moving eshop)
8) Two ivs:MoveAccountResponse will be made, change both ErrorCode response to <ErrorCode>0</ErrorCode> <= Nintendo's server will not allow your legacy account to be transfered but if everything above is done right the NNID transfer request (which we do NOT proxy since we did not touch the act module) WILL go through. First one is a dry run.
At this point your NNID will be associated with your Japanese N3DS and you will confuse Nintendo support if you ever call them since in their systems, a Japanese console is now associated with an American account. Do not try this.
However, even though the NNID is associated with your new console in Nintendo's servers, you still need to "activate" it by entering shop for the first time. Problem is there's likely some internal checks that prevents this "first time activation" from working. Luckily there's a workaround...
NNID Linking:
1) On N3DS, go into system settings and link existing NNID to the one you moved
2) Reboot into NTR mode, and run the following commands:
write(0xfffffd5,tuple(map(ord, "N3DS_SERIAL_HERE\0")),pid=0x7)
write(0x0013E74C,tuple(map(ord, "N3DS_SERIAL_HERE\0")),pid=0x22)
write(0x0010DD28, (0x00, 0x20, 0x08, 0x60, 0x70, 0x47), pid=0x25)
write(0x001314F8, (0x06, 0x9A, 0x03, 0x20, 0x90, 0x47, 0x55, 0x21, 0x01, 0x70, 0x53, 0x21, 0x41, 0x70, 0x00, 0x21, 0x81, 0x70, 0x60, 0x61, 0x00, 0x20), pid=0x25)
write(0x0010e44c, tuple(map(ord, "http://yourip:8888/%s%sa/\0")),pid=0x22)
3) Enter eshop (follow (*) on GetAccountStatusResponse) and login to NNID. Capture all requests.
3a) Specifically capture the request (headers and all) to https://account.nintendo.net/v1/api/oauth20/access_token/generate but abort it from your proxy! (Do not forward this request) <= this is the login request. we will use fake this request to log-on to the NNID now linked with you N3DS on your O3DS (which is no longer linked to your NNID!)
4) On O3DS create a new dummy NNID <= this is so when entering eshop, your 3DS will try to login to NNID
5) Load code.bin (or use 3ds_injector) and enter eshop (follow (*) on GetAccountStatusResponse)
6) Patch the request for https://account.nintendo.net/v1/api/oauth20/access_token/generate and replace the
entire request by the one you captured in 3a. Let the response through. <= Nintendo's servers now thinks you're logging in with your N3DS
7) Next request will be to https://account.nintendo.net/v1/api/people/@me/profile, change X-Nintendo-Device-ID, X-Nintendo-Serial-Number, X-Nintendo-Device-Cert to patch that from 3a <= this keeps the façade that you're logging in from your N3DS
7a) When response for @me/profile comes in, replace user_id with your dummy nnid username <= this assuages checks from your O3DS that the right user_id is logged in
7b) If it errors, you need to capture the correct @me/profile request. To do that, on the O3DS, close and re-enter eshop, and pass the oauth20 request through (no patches), then pass the @me/profile request through and save the response. Finally log-out of your NNID by either restarting eshop and replacing the next request to account.nintendo.net with an invalid Authorization header (replace with junk) or go into system settings -> NNID settings and setting auto-login to false <= basically there might be other checks on the profile response that I'm too lazy to look into
8) The next request is for https://account.nintendo.net/v1/api/provider/service_token/@me, replace X-Nintendo-Device-ID, X-Nintendo-Serial-Number, X-Nintendo-Device-Cert headers with that from 3a <= this is the key part! This request "activates" your NNID to be used on your N3DS. If we make this request from the N3DS though, it fails (likely a check on Nintendo's servers). However, when we do it from a 3DS of the correct region, it still activates it with the correct CtCert (which we replaced) but using the token requested with the O3DS.
9) Once that request succeeds (200 OK), your NNID is linked to your N3DS
eShop:
Every time you wish to use eShop on the N3DS, you must enter NTR mode and use the following commands (or use 3ds_injector):
write(0xfffffd5,tuple(map(ord, "N3DS_SERIAL_HERE\0")),pid=0x7)
write(0x0013E74C,tuple(map(ord, "N3DS_SERIAL_HERE\0")),pid=0x22)
write(0x0010DD28, (0x00, 0x20, 0x08, 0x60, 0x70, 0x47), pid=0x25)
write(0x001314F8, (0x06, 0x9A, 0x03, 0x20, 0x90, 0x47, 0x55, 0x21, 0x01, 0x70, 0x53, 0x21, 0x41, 0x70, 0x00, 0x21, 0x81, 0x70, 0x60, 0x61, 0x00, 0x20), pid=0x25)
(details: http://gbatemp.net/threads/creating-a-north-american-non-xl-new-3ds.381775/page-37#post-5459760)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment