Lockpick_RCM payload - Official Thread


Description

Lockpick_RCM is a bare metal Nintendo Switch payload that derives encryption keys for use in Switch file handling software like hactool, hactoolnet/LibHac, ChoiDujour, etc. without booting Horizon OS.

Source: https://github.com/shchmue/Lockpick_RCM
Payload: https://github.com/shchmue/Lockpick_RCM/releases

Due to changes imposed by firmware 7.0.0, Lockpick homebrew can no longer derive the latest keys. In the boot-time environment however, there are fewer limitations. That means the new keys are finally easy to dump!

Usage
  • Launch Lockpick_RCM.bin using your favorite payload injector or chainload from Hekate by placing it in /bootloader/payloads
  • Upon completion, keys will be saved to /switch/prod.keys on SD
  • If the console has Firmware 7.x, the /sept/ folder from Atmosphère or Kosmos release zip containing both sept-primary.bin and sept-secondary.enc must be present on SD or else only keyblob master key derivation is possible (ie. up to master_key_05 only)
Big thanks to CTCaer
For Hekate and all the advice while developing this!

Known Issues
  • Chainloading from SX will hang immediately due to quirks in their hwinit code, please launch payload directly
 

Attachments

  • AB1248EA-8BB9-448B-83F5-FF68C2579FB1.jpeg
    AB1248EA-8BB9-448B-83F5-FF68C2579FB1.jpeg
    11.2 KB · Views: 0
Last edited by shchmue,
Ha funzionato ma non è possibile ricavare le chiavi principali, quindi scarica solo alcune chiavi e nessuna di quelle importanti, in questo caso solo 158 chiavi di produzione

View attachment 503311
Sto analizzando questo commit per individuare eventuali chiavi errate.
https://github.com/Atmosphere-NX/At...fusee/program/source/fusee_key_derivation.cpp
Informazioni sugli errori:
Impossibile ricavare le chiavi master per dev.
Impossibile ricavare le chiavi principali per prod.
Lockpick non riesce a ricavare le chiavi principali perché la chiave temporanea keys->temp_key che dovrebbe essere valida non viene generata correttamente.
 
Last edited by oresterosso,
Sto analizzando questo commit per individuare eventuali chiavi errate.
https://github.com/Atmosphere-NX/At...fusee/program/source/fusee_key_derivation.cpp
Informazioni sugli errori:
Impossibile ricavare le chiavi master per dev.
Impossibile ricavare le chiavi principali per prod.
Lockpick non riesce a ricavare le chiavi principali perché la chiave temporanea keys->temp_key che dovrebbe essere valida non viene generata correttamente.
My italian is very bad, sorry.
 
  • Haha
Reactions: Blythe93
Is the original author dead? Or is he just not doing anything for the community anymore...?
:switch::hateit:

EDIT: Or... Who else knows the entire Horizon system better than SciresM? Can't he help you?
;)
 
Is the original author dead? Or is he just not doing anything for the community anymore...?
:switch::hateit:

EDIT: Or... Who else knows the entire Horizon system better than SciresM? Can't he help you?
;)
No, the original author is still active on the scene, simply, lot of people acting ungrateful and demanding new versions, acting like divas and drama queens telling him what is a bad coder and things like that, make him to be flying under the radar, really demanding people are the worst.
 
With a dev friend, we found that this function systematically crashed on the keys.c file

C++:
if (_titlekey_count == 0 || !titlekey_buffer) {
        free(text_buffer);
        return;
    }
    memset(text_buffer, 0, text_buffer_size);

    titlekey_text_buffer_t *titlekey_text = (titlekey_text_buffer_t *)text_buffer;

    for (u32 i = 0; i < _titlekey_count; i++) {
        for (u32 j = 0; j < SE_KEY_128_SIZE; j++)
   
s_printf(&titlekey_text[i].rights_id[j * 2], "%02x", titlekey_buffer->rights_ids[i][j]);
        s_printf(titlekey_text[i].equals, " = ");
        for (u32 j = 0; j < SE_KEY_128_SIZE; j++)
            s_printf(&titlekey_text[i].titlekey[j * 2], "%02x", titlekey_buffer->titlekeys[i][j]);
        s_printf(titlekey_text[i].newline, "\n");
    }

I have a wacky hypothesis about the bug which is probably totally wacky, but it could be caused by the s_print which inserts a \o each time which makes a continuous assembly of hex characters.
Post automatically merged:

After analysis (many thanks to Shadow256 for the time spent on it)

The exact culprit is :
C:
char *text_buffer = (char *)calloc(1, text_buffer_size);

So with the next line it works, but it's still not clean and there must be a problem somewhere that causes the calculations here to be incorrect or the loop to be mishandled

C:
char *text_buffer = (char *)calloc(1, text_buffer_size + 65);

It's not perfect, but it works. If you have any ideas for improvements, don't hesitate to remodel the source code.

1746612171025.png


1746615919294.png

Post automatically merged:

Source code + Functional binary for V1 Erista with patch
 

Attachments

Last edited by Zoria,
So with the next line it works, but it's still not clean and there must be a problem somewhere that causes the calculations here to be incorrect or the loop to be mishandled
Issue is in clamping text_buffer_size to 16K on the line above. There is no reason for it. You can choose any value bigger. For example 32K or 64K
 
shchmue is very active on the Team Reswiched discord but no longer works on LockPick (understandably).
Asking about a NIFM crash in that discord will get you immediately booted with no information or warning (because, I assume, the NIFM crash is/was because of sys-patch, which needed a fix). I seriously doubt mentioning lockpick will go over well.

EDIT: Or... Who else knows the entire Horizon system better than SciresM? Can't he help you?
;)
LOL, no. This is a simple (if you actually know how to code) coding error. Nothing to do with horizon, whatsoever. It runs on bare metal, without horizon even loaded. Also, SciresM wouldn't touch Lockpick with a 10 foot pole, nor would he ever help you with it. He's smart and doesn't want to open a Window for Ninty Ninjas to come sue him (since it's pretty obvious by now that they can't do anything about Atmosphere... it's all legit).


Issue is in clamping text_buffer_size to 16K on the line above. There is no reason for it. You can choose any value bigger. For example 32K or 64K
LOL... I thought it was as simple as that but was afraid to mess with the code. Thanks a bunch!

From my own build just now:

lockpick_rcm.png


And all I did was change line 575 to:

Code:
u32 text_buffer_size = MAX(_titlekey_count * sizeof(titlekey_text_buffer_t) + 1, SZ_32K);

the end previously said SZ_16K.

Tested on Erista. Not messing with my OLED until everything is out of testing and into release mode.
 
Last edited by urherenow,
I kind of wish @mrdude

Asking about a NIFM crash in that discord will get you immediately booted with no information or warning (because, I assume, the NIFM crash is/was because of sys-patch, which needed a fix). I seriously doubt mentioning lockpick will go over well.


LOL, no. This is a simple (if you actually know how to code) coding error. Nothing to do with horizon, whatsoever. It runs on bare metal, without horizon even loaded. Also, SciresM wouldn't touch Lockpick with a 10 foot pole, nor would he ever help you with it. He's smart and doesn't want to open a Window for Ninty Ninjas to come sue him (since it's pretty obvious by now that they can't do anything about Atmosphere... it's all legit).



LOL... I thought it was as simple as that but was afraid to mess with the code. Thanks a bunch!

From my own build just now:

View attachment 503405

And all I did was change line 575 to:

Code:
u32 text_buffer_size = MAX(_titlekey_count * sizeof(titlekey_text_buffer_t) + 1, SZ_32K);

the end previously said SZ_16K
will there be a new updated release ?
 
You can either do :
C:
 u32 text_buffer_size = MAX(_titlekey_count * sizeof(titlekey_text_buffer_t) + 1, SZ_16K * 2);
Either make
C:
 u32 text_buffer_size = MAX(_titlekey_count * sizeof(titlekey_text_buffer_t) + 1, SZ_32K);
Technically speaking, both work without a hitch
Normally, there should be no more problems of this kind (at least with this function).
 
With a dev friend, we found that this function systematically crashed on the keys.c file

C++:
if (_titlekey_count == 0 || !titlekey_buffer) {
        free(text_buffer);
        return;
    }
    memset(text_buffer, 0, text_buffer_size);

    titlekey_text_buffer_t *titlekey_text = (titlekey_text_buffer_t *)text_buffer;

    for (u32 i = 0; i < _titlekey_count; i++) {
        for (u32 j = 0; j < SE_KEY_128_SIZE; j++)
  
s_printf(&titlekey_text[i].rights_id[j * 2], "%02x", titlekey_buffer->rights_ids[i][j]);
        s_printf(titlekey_text[i].equals, " = ");
        for (u32 j = 0; j < SE_KEY_128_SIZE; j++)
            s_printf(&titlekey_text[i].titlekey[j * 2], "%02x", titlekey_buffer->titlekeys[i][j]);
        s_printf(titlekey_text[i].newline, "\n");
    }

I have a wacky hypothesis about the bug which is probably totally wacky, but it could be caused by the s_print which inserts a \o each time which makes a continuous assembly of hex characters.
Post automatically merged:

After analysis (many thanks to Shadow256 for the time spent on it)

The exact culprit is :
C:
char *text_buffer = (char *)calloc(1, text_buffer_size);

So with the next line it works, but it's still not clean and there must be a problem somewhere that causes the calculations here to be incorrect or the loop to be mishandled

C:
char *text_buffer = (char *)calloc(1, text_buffer_size + 65);

It's not perfect, but it works. If you have any ideas for improvements, don't hesitate to remodel the source code.

View attachment 503390

View attachment 503399
Post automatically merged:

Source code + Functional binary for V1 Erista with patch

Wow mate, That worked.

First class!!! Now works on Mariko & Erista v1 and all keys are read without errors!!!
@impeeza Please test this under your Erista to see if it works without errors.
Full dump of keys on my SysNAND
1746629587918.png

LOL... I thought it was as simple as that but was afraid to mess with the code. Thanks a bunch!
You and me, me hypothesis was a overflow, but as stated before I have not the knowledge, my guess was on the lines using text_buffer_size but I never think about the definition itself :P

And all I did was change line 575 to:

Code:
u32 text_buffer_size = MAX(_titlekey_count * sizeof(titlekey_text_buffer_t) + 1, SZ_32K);
the end previously said SZ_16K.

The value SZ_16K and SZ_32K are both defined on the file "bdk/utils/types.h"

will there be a new updated release ?
very soon :P
You can either do :
C:
 u32 text_buffer_size = MAX(_titlekey_count * sizeof(titlekey_text_buffer_t) + 1, SZ_16K * 2);
Either make
C:
 u32 text_buffer_size = MAX(_titlekey_count * sizeof(titlekey_text_buffer_t) + 1, SZ_32K);
Technically speaking, both work without a hitch
Normally, there should be no more problems of this kind (at least with this function).
I do prefer SZ_32K as both they are defined on the code, and as far I know is better to use a variable than a math expression.

My guess is the original code uses 16K because as being a payload the resources are scare, and you must use the minimum memory as possible, before key 13 all keys fit on 16K but now they do not, I do hope 32K is under the memory usage limit for payloads.

So many thanks to all of you, THIS IS WHAT MAKES THE SCENE SO GREAT people working together to achieve great things.

I am starting a PR on the Repo.
 
You can either do :
C:
 u32 text_buffer_size = MAX(_titlekey_count * sizeof(titlekey_text_buffer_t) + 1, SZ_16K * 2);
Either make
C:
 u32 text_buffer_size = MAX(_titlekey_count * sizeof(titlekey_text_buffer_t) + 1, SZ_32K);
Technically speaking, both work without a hitch
Normally, there should be no more problems of this kind (at least with this function).
I could not find any of these code lines in your source code and yet it works. "SZ_16K" is set in the corresponding line.
 
Last edited by Muxi,

Site & Scene News

Popular threads in this forum