Some Typo's in your keygen scripts.
Closed this issue ยท 9 comments
In both keygen files, you need to change to the following:
import argeparse
change to
import argparse
Also in the file: scripts/erista_keygen.py, you have an error on the path on line 21
subprocess.run(f'hactoolnet --keyset prod.keys -t pk11 0100000000000819/romfs/nx/package1 --outdir 0100000000000819/romfs/nx/pkg1', stdout = subprocess.DEVNULL)
Change to:
subprocess.run(f'hactoolnet --keyset prod.keys -t pk11 0100000000000819/romfs/a/package1 --outdir 0100000000000819/romfs/nx/pkg1', stdout = subprocess.DEVNULL)
Modding both files fixes errors - you could also add a python requirements.txt , If not, users should run - "pip install argparse" to install that module to python.
Thanks for the keygens though, they work well.
Change to:
subprocess.run(f'hactoolnet --keyset prod.keys -t pk11 0100000000000819/romfs/a/package1 --outdir 0100000000000819/romfs/nx/pkg1', stdout = subprocess.DEVNULL)
This actually is not broken.
/a/ is for mariko.
/nx/ is for erista, the reason it's failing is because you do not have the appropriate keys. (they are not identical, but they produce the same master_key at the end)
the keys required are described in the README.md, but the tl:dr really is you need tsec_secret_26 (acl 0x00, https://switchbrew.org/wiki/TSEC#ACLs ) to derive package1_key_%% beyond 6.2.0, and tsec_secret_26 requires hardware glitching of the tsec aes scp key register and bruteforcing. (can be done with rcm payload, though none that do this task are public, and bruteforcing part is done on a pc)*
here's some reading material if you are interested in that, combined its all relevant, but plutoo's gist is what is required:
disclaimer; none of these actually show you what you have to do, or tell you what to do:
https://gist.githubusercontent.com/plutooo/733318dbb57166d203c10d12f6c24e06/raw/15c5b2612ab62998243ce5e7877496466cabb77f/tsec.txt
https://hexkyz.blogspot.com/2021/11/je-ne-sais-quoi-falcons-over-horizon.html
https://www.unknowncheats.me/forum/3141470-post1.html
https://github.com/vbe0201/faucon
https://github.com/CAmadeus/falcon-tools
https://gitlab.com/Nxyoom/tsec-exploration
https://github.com/Thog/ghidra_falcon/releases/tag/master
https://github.com/envytools/envytools
"if you're using hekate you can try to replicate this with something like max77620_regulator_set_voltage(REGULATOR_SD0, 720000 + extra); and synchronize the start and end of the glitch using the falcon mailbox."
something like this:
things to get working:
stage 0:
verify keys in succession are dumped and written on screen/to sd card
stage 1:
if falcon mailbox X
print content of mailbox to screen/to sd card
verify screen/to sd card prints
stage 2:
stop if other mailbox
verify stop after recieving mailbox
stage 3:
if mailbox
print sor1
if other mailbox
stop
stage 4:
mass spam print sor1 of many csecrets
verify output
stage 5:
repeat with csigenc of 00
verify authhash/csecret 00 is printed to screen/to sd card
stage 6:
use mailbox condition to set voltage
print csigenc
use other mailbox to revert
main.asm (falcon heavysecure entry example for dumping acl 0x03 tsec secrets, built from requiem from https://github.com/CAmadeus/falcon-tools )
.section #ns_code
// Set up the Falcon stack pointer.
mov $r13 #FALCON_HWCFG
iord $r13 I[$r13]
shr b32 $r13 0x9
and $r13 0x1FF
shl b32 $r13 0x8
mov $sp $r13
lcall #main
exit
pushdef(`key_data_addr', `$r5')
main:
mov $r15 -0x10
add $sp -0x11C
mpush $r8
// Allocate memory for the Key Data table.
mov $r9 $sp
add b32 $r9 $r9 0xC4
and key_data_addr $r9 $r15
// Copy Key Data into DMEM.
mov b32 $r10 key_data_addr
mov $r11 #KEY_TABLE_START
mov $r12 #KEY_TABLE_SIZE
lcall #memcpy_i2d
// Copy the signed microcode portion to DMEM.
clear b32 $r10
mov $r11 #HS_PAYLOAD_PHYS_ADDR
ld b32 $r12 D[key_data_addr + 0x20]
lcall #memcpy_i2d
// Remap the signed microcode and tag it as secure.
mov b32 $r11 $r10
mov $r10 #HS_PAYLOAD_START
mov b32 $r13 $r10
mov $r14 0x1
lcall #memcpy_d2i
// Transfer the MAC of the secure payload into crypto register 6.
clear b32 $r7
mov b32 $r8 key_data_addr
sethi $r8 0x60000
cxset 0x2
xdst $r7 $r8
xdwait
// Transfer the seed for the fake-signing key into crypto register 7.
clear b32 $r7
add b32 $r8 key_data_addr 0x10
sethi $r8 0x70000
cxset 0x2
xdst $r7 $r8
xdwait
// Load in the cauth details for Heavy Secure mode authentication.
ld b32 $r9 D[key_data_addr + 0x20]
shl b32 $r9 0x10
mov $r15 #HS_PAYLOAD_START
shr b32 $r15 0x8
or $r9 $r15
mov $cauth $r9
// Jump to Heavy Secure Mode!
lcall #HS_PAYLOAD_START
mpopaddret $r8 0x11C
popdef(`key_data_addr')
include(`base_define.asm')
include(`mmio.asm')
include(`memcpy.asm')
include(`memcpy_i2d.asm')
include(`memcpy_d2i.asm')
include(`tsec_wait_dma.asm')
include(`tsec_dma_write.asm')
include(`tsec_set_key.asm')
.align 0x100
.section #ns_data 0x200
.equ #KEY_TABLE_SIZE 0x7C
KEY_TABLE_START:
HS_PAYLOAD_MAC: .skip 0x10
HS_PAYLOAD_SEED: .skip 0x10
HS_PAYLOAD_SIZE: .b32 0x00000000
.align 0x100
HS_PAYLOAD_PHYS_ADDR:
.section #hs_code 0x200
.equ #HS_PAYLOAD_START 0x200
hs_main:
mov $r11 #FALCON_MAILBOX1
mov $r12 0xBADC0DED
iowr I[$r11] $r12
// load csecret with acl value of 0x03 push it into sor1 with #tsec_set_key to be readable ( https://switchbrew.org/wiki/TSEC#Secrets )
csecret $c0 0x39 // loads the secret desired
cxset 0x2 // changes target for next operation to cryto instead of DMA
xdld $r10 $r10 // load from crypto to $r10, $r10 is equivelant of $c0
xdwait // waits for xdld with cxset to complete
lcall #tsec_set_key // this takes what is stored in $r10 and pushes it through sor1
// Clear the HS signature and return back to NS mode.
csigclr
ret
.align 0x100
I am considering pushing a smaller writeup on this, but it is one of my low-priority side-projects.
ideally i'd figure out how to rebase it to mainline hekate as it has features for this and better code to amend. (i currently use a hwinit based launcher, using the gplv2 example from https://gitlab.com/Nxyoom/tsec-exploration/-/tree/main/launcher )
i have pushed this: https://github.com/borntohonk/falcon-tools which is an amended fork of both: https://github.com/CAmadeus/falcon-tools and https://gitlab.com/Nxyoom/tsec-exploration/-/tree/main/launcher
which is preconfigured to dump acl 0x13/0x03 secrets (though build enviroment is very much linux based)
and a sample pushed https://github.com/borntohonk/falcon-tools/releases/tag/dump_readable_secrets (which i have only tested on my own erista console)
edit: if you have years to spare, or want to try a luck-based approach, you also could use this gimmick/joke bruteforcer i made.
from hashlib import sha256
from multiprocessing import Process
import os
from datetime import datetime
list = [
'7c20cef183f6184f7c5a877040ec63fa44ad42178b1aa6af9932568fc468e426', '43449338c1bc8ceb1b3232a611f955f9095254f492117a158528589cd16f2930', '2816295b45e08837846afbe093cd4a3ab5492174798d2e1872fceeccc0463e0f', 'eb06713d87ad94c9832549eb2057f014b5fd34853c0f8ce4108aecd3b23c8a58',
'7fafa6babbc8600ec42969ac81e16701320c4611e4cc910b4c51adcf14363212', '49371c6ccb2cf64c10633164c202a3f7d03a17a0e0098ab7bcd9f84ae9a4805c', '8745f02b86bbf722654e43b1fef32ac22c740d10aa4432b93d5b2035523c2c94', 'd6ecab46e243d80af83ca5f8bdf440b595459ecb39f2e083a50f793ade04822c',
'8ca7cc625a593699870e11056aa52124cc5565df0d934b6431854910314b6c51', '6836e01fce672b276e3746fac8e7a133a986c7922f2bddebd3c231fcd6a6bac5', '96240c628444c83b527fb8de96bbc39e3c9ef4c46952286a57f9d7efe0847ae2', 'affa6d401592ca2ac21451064a632b6eecc72bb887d29ac93ce7c0de3e2c9212',
'd19495a97b6dd1dac8ee099107c731cdab49c0e1ec5b3cd1b38480d70dbe7003', '1c081ad4d8c7da9291ec4f5de06e558177fc0faf613fb7d9ff0005ef66f63d61', 'b2429bfb5de59191b825f9675c4320b5e1dfb5cc0e7a8161c5dab64313eb9a63', '34141a2aa355cfa1d14ec921db288d1cd04c810c3c30c69abb34bb1542a9966f',
'678d1b92f9dd7e46bdc9bd96378896f58da01e933d5056c812c9d3a948b709b4', '7e0aec4bfd4160035d04aec8e2aa0e7668ae769681f8a2c6ba62d31791f072aa', '641622358b351d50e7f3f2cfee6864a68fa7803a649a2bcade226a99a143918a', '86899161828e7b3ebb8b90e73261d2e34b8b5314f070f9811cf4173570024665',
'735146a321f46b7d130226b0aea05d2042363374b0674e9015d80c4eb17f6e7b', '9c90367e3b4191706f1018861f1622e233d905445e6f2463bedbdea2f4395205', '6e607b4265f213530df9d6c9574af4a3a6d5c7282f19214144ac03cda69b68f1', 'fdc6ed08368fc2f19f8f8979fe7545f6f9136897d369045d3afd160756d82c3d',
'40c4d1dfb08fb9963ad20076681651a124f325a6065db51c1b88b2efd8799d01', 'eb9b9813c0a08f7c6af56907e09c5df8e53d2d4299914038fa867578ced8b656', 'c62e4708e163252adeac56f749cf025a8921a86f786e2cc396304ebd2e625354', '0bde3d9cb209d1c132d1c9e80c0ccf595e3feef411be7ee590e181af57421815',
'a9dc5a0a27de9214909c8dd933cdd82e6df1cc2d09cb654466406e2cebad0017', 'c58b9370c0c67dbebaf8925f734e29940a3de70d3815fd644f2835f4f0ebb106', '02667ae7cbe9a608a648eec9876dc66159068aceb872901a085ce6968f5d17a1', '2885bc4f35d01ad469997b6a36a9bfa2976d62ae5dc48a1f96ecbc73bc770528',
'14fc0140daafc49631356da9a6ef5d96ca20b8d45ce63e4227aededbcd0056bf', '5ad7845f27ea0aa7c717ff56d4cffe5d060a374d86a0e820bdc13fc5f553226b', 'ab1cf064eedfeaa7f71db717bfbcfdbd73b6db7ba356e37cc299d8b731cffe24', '81fdc5ebcd592f59a063a66155f6b08e48cc89e19c6fb8d3a2756c9ac0590f8f',
'c8312de41a98f7c55c4e21184b1f34a7578145c2cbeca78a9556978dd84939e3', 'b20226d3accc9e554278f3ba7157460ebff8a88757e850d57591342b0a275542', 'cefe01c9e3eeef1a73b8c10d742ae386279b7dff30a2fbc0aabd058c1f135833', 'd3ade4766781a5d9862b350867c2572dcb7f513b28c3a812170cd856dfb54f95',
'73f4a07cd1f061f81c42b32e3dd1ffa0ac1114d40df92205869e60a1e537d2ac', 'd97b8509b66ae9b33ed6d1e46b37449ed6f7f3e7f4bc03a59004994ff833bb71', '08a0edf7bf91d7fa685ca77246b8394fa4edd0e06639e53e6fa835436b09560f', '6d3a215979ae17a947e7c2772d1efec9b0ac9b0063f4e0a64fe93f779fc70188',
'20c358eeed4f03cc03ddbad4f9cf9e6f83a86c61fe434ee259789a63ba2178b7', '07923cbd0e19d3b8c81d3f5d4df8ef58ec667f94e6096897de34c1ebf878b2b0', 'b8706c9d52b7fe020c3c833cfde328dbcda24c290be60c658b3c1784da85340b', 'e0c6273094f499180139a06133e582565cc1cd23478a6180914950a672e3bfaf',
'3477d86ed721fd5112c94a566f26b4d30cd7ae78de1b047eb21a709a7934d073', 'd2bf372d3a1b652a31b0fa1264086c8fdce8ab491889dce2cfb4db71eab758b8', 'fc65d00eb14406f76a940368722c4f3b8ab11d1abf44e32499103492cf714af9', 'fa7f4a5cb39ae9205177f3da8f8c2f88ec7f8d14b8c6f75b2dbb661f30ec076d',
'4aa215afd1a0ab118ab60db1fbc5ee769907a1b58813ec417e7f1519a5cc4243', 'ae64ed29f1158feee2c3e858b2868197c173b07e6d1d281dbd458449770c492b', '083bd0a21da79ae6b63c9e01035fad9334983c79a43d555dba5481c6d531b30f', '9cc2735bc70f0c756279c41b85dd558e00783dd8ec4202f4db0f6c384b43dda2',
'90483d58fc3e7c298b353f3d9295d8a81d8bb9f5182bcfcf3c8c60e9b6537aec', '78a4c4ad790921ab5c6f3224ea394fb53e576110d1fa467b3aa942b5c141cfa8', 'a28b03e2bee0c18640f9607db3cf430af0fc7a9b61b002f3369333e13dec3080', 'eec13d2a63a89e35834d6e1c2ca879ef556e3e970efaf08bee406979f271e9a9',
'29b30980914a0201a195dab7c5494d2ca9c94205619c2f91dd74ddeea24d14f0', 'aeff5b69a19c6a1b767dfae9fd57ffcb11ba2f5eb34f0e013a922d9474218d11', '6b07bc90e01a40ae51fd718e2ef751fb174c14c8cb4f68a00be847f020bdc1a6', '374708fff7719dd5979ec875d56cd2286f6d3cf7ec317a3b25632aab28ec37bb'
]
def random_hex_string(length=16):
return os.urandom(length).hex()
def loop():
for i in range(10000000000000000000000000000):
key = random_hex_string()
hash = sha256(bytes.fromhex(key)).hexdigest()
keyhash = f'key: {key}, hash: {hash}'
if hash in list:
match_found = open('./key_match.ini', 'a')
match_found.write(f'key is found: {key} with hash: {hash}\n')
match_found.close()
print(keyhash)
if __name__ =="__main__":
p1 = Process(target=loop)
p2 = Process(target=loop)
p3 = Process(target=loop)
p4 = Process(target=loop)
p5 = Process(target=loop)
p6 = Process(target=loop)
p7 = Process(target=loop)
p8 = Process(target=loop)
p1.start()
p2.start()
p3.start()
p4.start()
p5.start()
p6.start()
p7.start()
p8.start()
p1.join()
p2.join()
p3.join()
p4.join()
p5.join()
p6.join()
p7.join()
p8.join()
print("done")
now = datetime.now()
current_time = now.strftime("%H:%M:%S")
print("it ended at this time =", current_time)
```
Nice, thanks for the info. I've just made a test c# keygen app now and it seems to work fine, so far I have this:
hactoolnet --keyset decrypt.keys -t switchfs Firmware --title 0100000000000819 --romfsdir 0100000000000819/romfs/
hactoolnet --keyset decrypt.keys -t pk11 0100000000000819/romfs/a/package1 --outdir 0100000000000819/romfs/a/pkg1
decrypt.keys at this point only has:
mariko_bek = 6Axxxxx
mariko_kek = 41xxxxx
At this point when we can see the OEM Bootloader Version:
example:
Firmware 15.xx - OEM Bootloader Version: 0F (mariko_master_kek_source_0E)
Firmware 16 - OEM Bootloader Version: 10 (mariko_master_kek_source_0F)
Firmware 17 - OEM Bootloader Version: 11 (mariko_master_kek_source_10)
Firmware 18 - OEM Bootloader Version: 12 (mariko_master_kek_source_11)
Now we can write to our decrypt.keys - mariko_master_kek_source_(OEM Bootloader Version -0x1) = xxx
I wrote the program to get the key from Decrypted.bin automatically and append decrypt.keys, so now we can run hactool to output prod.keys with the new values added.
hactoolnet --keyset "decrypt.keys" -t keygen > prod.keys
I actually wrote a program called IPS Patch creator ages ago that can decrypt the switch firmware if you know the keys, and now I have this info for the keygen I can add this keygen code into it so that it can decrypt the firmware automatically without needing to update the keys manually. So thanks for your scripts are they we very helpfull in understanding how these keys are derived.
I actually wrote a program called IPS Patch creator ages ago that can decrypt the switch firmware if you know the keys, and now I have this info for the keygen I can add this keygen code into it so that it can decrypt the firmware automatically without needing to update the keys manually. So thanks for your scripts are they we very helpfull in understanding how these keys are derived.
yeah, i actually wrote the means to automatically update using mariko bek/kek, because the mariko package is always accessible with keys from a lower iteration because it is required for firmware updates, so initiating keygen while processing firmware files ensures you always have the latest mariko_master_kek_source which also ensures you will always have the latest mariko_master_kek, which in turn will provide you the latest master_key, etc etc
(you can always open 0100000000000819/romfs/a/package1, but not other nca's until you have the latest keyset, but with mariko package1 you obtain the master key encryption key source, which lets you just generate the keys you need)
This is nice to have information. I am so glad you posted those scripts as they make life alot easier without needing to update lockpic_rcm now. Before I was needing to wait until Atmosphere git was updated so I could get the keys to update that but now I don't need to anymore. This makes writing patches much faster now as I can dump FW as soon as it's available and then decrypt it, then use ghidra to dump decrpyted modules into c code - which makes it so much easier to trace the sub's where to patch if that patterns I normally use change. I am pretty chuffed I came across your git yesterday as I have learned alot from it.
Cheers.
no problem mate
PS. I know the Bootloader Version is shown in hactoolnet output, but for speed in code it seems to be at header address 0x150 in /0100000000000819/romfs/a/package1. For your scripts you can read address and use it to write mariko_master_kek_source_xx without having a prod.keys file first and then you can just generate a brand new file from scratch without appending anything.
PS. I know the Bootloader Version is shown in hactoolnet output, but for speed in code it seems to be at header address 0x150 in /0100000000000819/romfs/a/package1. For your scripts you can read address and use it to write mariko_master_kek_source_xx without having a prod.keys file first and then you can just generate a brand new file from scratch without appending anything.
I actually was just about to push a commit with that, as when i first made it it was lazily done.
edit: i realize what you're asking was something different, i guess that can be done also, but that depends on me providing mariko_bek and mariko_kek in plaintext too, which is why it works with an existing key file.
Thanks for updating your scripts, the new updated ones are better and work well. I've been busy all day but I'll have a look in a while and see if I can find anything else that could, but all seems good now on my end - from a noobs perspective :-).