Hacking Discussion Info on SHA-256 hashes on FS patches

linuxares

The inadequate, autocratic beast!
Global Moderator
Joined
Aug 5, 2007
Messages
13,272
Trophies
2
XP
18,084
Country
Sweden
@linuxares if I may, I'd like to suggest the developer role for mrdude, though I'm not sure who to contact for that, if you can consider or if someone else is in charge of that, please :P
It's up to him to apply for it. We don't normally randomly give them out, since not everyone wants them ;P

EDIT: But I do agree :3
 

redneon

New Member
Newbie
Joined
Aug 3, 2022
Messages
3
Trophies
0
Age
27
Location
Spain
XP
41
Country
Spain
Here you go windows users - this is a small test program made in c# (so you'll need net framework installed on your computer if you don't already have it) for creating Atmosphere Loader IPS patches. I just knocked it together today quickly and will post the code up on github when I make a nice gui + add the ES/FW stuff, maybe even I'll add a few extra things while I'm at it - in the meantime you can test it if you want, no need for python to be installed with this and no need for key files as you don't need those for the Atmosphere loader, so nothing illegal is in this program. GUI is crappy just now, obviously I'll make it nicer once the code is all done.

To use - open the program, drag your package3 file onto it - the Atmosphere loader IPS patch will be made automatically if everything went to plan.
Hey! I'm a noobie here and I don't understand what should I do with the new file your program created. What do I have to do? I loaded the package3 file and now I have a new .ips file. Thanks in advance!
 

mrdude

Developer
Developer
Joined
Dec 11, 2015
Messages
3,071
Trophies
1
Age
56
XP
8,226
Hey! I'm a noobie here and I don't understand what should I do with the new file your program created. What do I have to do? I loaded the package3 file and now I have a new .ips file. Thanks in advance!
This program isn't for you, if you don't even know what it does you are better skipping it and downloading pre-made patch bundles and following some sort of guide.
 
  • Like
Reactions: peteruk and impeeza

redneon

New Member
Newbie
Joined
Aug 3, 2022
Messages
3
Trophies
0
Age
27
Location
Spain
XP
41
Country
Spain
Give your switch to a 14 year old kid that is able to read, direct them to this post, they will sort it out for you.
Thank you for your kindness. As I am not a native speaker nor I have any experience doing this sort of things, I can easily miss stuff that I don't understand.
 
  • Like
Reactions: peteruk

dogcsty

Well-Known Member
Newcomer
Joined
Dec 2, 2021
Messages
47
Trophies
0
XP
227
Country
United States
Just to update you guys on what I'm working on. As some of you might know I'm working on a homebrew app allowing to directly generate the sigpatches from the switch.


I've basically done the hard part which was finding the files of the current firmware and porting hactool (which was a mess btw I think I'm going to release a library for this so that people can play with it and manipulate ncas from the switch).

The only thing left for me to do is actually port the algorithm from python to C which shouldn't be too much of a trouble. I'm going to work on it in a week or two.
 
Last edited by dogcsty,

mrdude

Developer
Developer
Joined
Dec 11, 2015
Messages
3,071
Trophies
1
Age
56
XP
8,226
Just to update you guys on what I'm working on. As some of you might know I'm working on a homebrew app allowing to directly generate the sigpatches from the switch.

I've successfully ported the hactool tool on the switch and I'm able to get the firmware files I need from the switch to generate the IPS.
Here is an example:


I've basically done the hard part which was finding the files of the current firmware and porting hactool (which was a mess btw I think I'm going to release a library for this so that people can play with it and manipulate ncas from the switch).

The only thing left for me to do is actually port the algorithm from python to C which shouldn't be too much of a trouble. I'm going to work on it in a week or two.

If you want my advice on porting python scripts - ignore the old way to generate ES patches and just use the Alt (new one) as you only need to patch in 1 place for this and you can do a wildcard search for where to patch. Good job though, this will be a really good release if you manage to pull it off.
I'm still doing a little bit at a time on the Windows version:
zFi2Ytw.png
 
Last edited by mrdude,

mrdude

Developer
Developer
Joined
Dec 11, 2015
Messages
3,071
Trophies
1
Age
56
XP
8,226
Also @dogty - this is how the code looks in c# for doing the loader part (it might be easier to see what's going on here)

Code:
/*Code by Mrdude - what this program does....
        First: Open package3 and search for the loader offsets + size.
        Second: Dump the loader stored inside package3.
        Third: Get the sha256 value of the dumped loader.
        Fourth: Use hactool to decrypt the dumped loader.
        Fifth: Find the offset for this hex - 01c0be121f00016b - in the decrypted loader.
        Sixth: Create the ips patch.
        */
        string loaderpath; //create variable for package3 file path location.
        string shaValue; //create a variable to store the sha256 value.
        int patch_offset; //create a variable to store the ips patch offset.

        public Form1()
        {
            InitializeComponent();
            richTextBox1.Text += "This page will create a loader patch for Atmosphère NX" + "\n\n" +
                "Click load and select your package3 file.";
        }

        private void button1_Click(object sender, EventArgs e)
        {
            load();
        }

        public void load()
        {
            try
            {
                OpenFileDialog openFileDialog = new OpenFileDialog();
                openFileDialog.Filter = "package3|package3|fusee-secondary|fusee-secondary.bin|All Files (*.*)|*.*";
                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {

                    loaderpath = openFileDialog.FileName;
                    bool myfile = loaderpath.Contains("package3") || loaderpath.Contains("fusee-secondary");
                    if (myfile)
                    {
                        richTextBox1.Clear();
                        richTextBox1.Text += "Selected file: " + loaderpath;
                        FindBytes();
                    }

                    else
                    {
                        MessageBox.Show("File not supported.");
                    }
                }
            }

            catch (Exception error)
            {
                MessageBox.Show("Error is: " + error.Message);
            }
        }

        private void Form1_DragDrop(object sender, DragEventArgs e)
        {
            try
            {
                var files = (string[])e.Data.GetData(DataFormats.FileDrop);
                loaderpath = Path.GetFullPath(files[0]);
                bool myfile = loaderpath.Contains("package3") || loaderpath.Contains("fusee-secondary");
                if (myfile)
                {
                    //loaderpath = loaderpath.Replace(@"\", @"\\");
                    FindBytes();
                }
                else
                {
                    MessageBox.Show("File not supported.");
                }
            }

            catch (Exception error)
            {
                MessageBox.Show("Error is: " + error.Message);
            }
        }

        private void FindBytes()
        {
            try
            {
                int i;
                int j;
                byte[] ByteBuffer = File.ReadAllBytes(loaderpath);
                //byte[] StringBytes = new byte[6] { 0x4C, 0x6F, 0x61, 0x64, 0x65, 0x72 }; --this is the same as "Loader" (hex 4C ascii value is 76 same as L)
                byte[] StringBytes = Encoding.UTF8.GetBytes("oader"); //new atmosphere uses uppercase L so skip looking for that to avoid problems


                for (i = 0; i <= (ByteBuffer.Length - StringBytes.Length); i++)
                {
                    if (ByteBuffer[i] == StringBytes[0])
                    {
                        for (j = 1; j < StringBytes.Length && ByteBuffer[i + j] == StringBytes[j]; j++) ;
                        if (j == StringBytes.Length)
                            break;
                    }
                }

                int startpos = (i - 17); // where the ascii text "oader" is found (minus 17 bytes)
                int sizeloc = (startpos + 4); //size of the loader is found 4 bytes from the startpos
                var location = new byte[4];
                var size = new byte[4];

                //MessageBox.Show(i.ToString()); //only used for debugging.

                //get loader start location
                using (BinaryReader reader = new BinaryReader(new FileStream(loaderpath, FileMode.Open)))
                {
                    reader.BaseStream.Seek(startpos, SeekOrigin.Begin);
                    reader.Read(location, 0, 4);
                }

                //get the size of the loader
                using (BinaryReader reader = new BinaryReader(new FileStream(loaderpath, FileMode.Open)))
                {
                    reader.BaseStream.Seek(sizeloc, SeekOrigin.Begin);
                    reader.Read(size, 0, 4);
                }

                //convert bytes to int:
                var loadersize = BitConverter.ToUInt32(size, 0);
                var startloc = BitConverter.ToUInt32(location, 0);
                var end = (loadersize + startloc);

                //call code to dump the loader here now we know the size and start and end locations.
                using (var output = File.Create("dumped_loader")) //set path of dumped_loader
                using (var input = File.OpenRead(loaderpath)) //open package3 so we can dump the loader
                {
                    // if there's timing issues with the dumped loader not being created fast enough - put this in a new thread.
                    AppendChunk(output, input, startloc, end); //dump the loader
                }

                //revese location bytes
                Array.Reverse(location);
                string location_hex = BitConverter.ToString(location);

                //reverse end location bytes
                byte[] endlocation = BitConverter.GetBytes(end); //convert end int location to byte array
                                                                 //MessageBox.Show(String.Join("",endlocation.Select(x => x.ToString("X2"))));
                Array.Reverse(endlocation);

                //Not used - but can mod byte array manually....for changing instructions.
                // UInt32 revloc = ReverseBytes(end);

                richTextBox1.Text += "\n" + "Loader size: " + loadersize.ToString() + " bytes";
                richTextBox1.Text += "\n" + "Loader start offset: 0x" + location_hex.Replace("-", "");
                richTextBox1.Text += "\n" + "Loader end offset: 0x" + String.Join("", endlocation.Select(x => x.ToString("X2")));

                //loader should be dumped now - so let's get the sha256 value;
                Sha256();

                //Now we can decrypt the dumped loader...
                Decrypt_loader();

                //now try to find the patch location in the decypted loader
                FindloaderPatch();

                //write ips patch
                WriteIPS();

                //remove decrypted loader now.
                if (checkBox_decrypted.Checked)
                {
                    File.Delete("dec-loader.bin");
                    richTextBox1.Text += "\n" + "Decrypted loader cleaned up";
                }

                richTextBox1.Text += "\n" + "Finished!";

            }

            catch (Exception error)
            {
                MessageBox.Show("Error is: " + error.Message);
            }

        }

        private void makedirs()
        {
            try
            {
                if (!Directory.Exists("atmosphere"))
                {
                    Directory.CreateDirectory("atmosphere");
                }
                
                if (!Directory.Exists("atmosphere\\kip_patches"))
                {
                    Directory.CreateDirectory("atmosphere\\kip_patches");
                }
                
                if (!Directory.Exists("atmosphere\\kip_patches\\loader_patches"))
                {
                    Directory.CreateDirectory("atmosphere\\kip_patches\\loader_patches");
                    richTextBox1.Text += "\n" + "Patch directories created";
                }
            }
            
            catch (Exception error)
            {
                MessageBox.Show("Error is: " + error.Message);
            }
        }
        
        private void WriteIPS()
        {
            try
            {
                //create Atmosphere ips directory if it doesn't exist.
                makedirs();
                using (var stream = File.Open("atmosphere\\kip_patches\\loader_patches\\" + shaValue + ".ips", FileMode.Create))
                {
                    using (var writer = new BinaryWriter(stream, Encoding.UTF8, false))
                    {
                        byte[] StartBytes = new byte[] { 0x50, 0x41, 0x54, 0x43, 0x48, 0x00 };
                        byte[] EndBytes = new byte[] { 0x00, 0x01, 0x00, 0x45, 0x4F, 0x46 };
                        byte[] Middlebytes = BitConverter.GetBytes(patch_offset);

                        writer.Write(StartBytes);
                        
                        //stupid code for testing = also reverse bytes
                        if (patch_offset > 0 && patch_offset <= 255)
                        {
                            writer.Write(Middlebytes[0]);
                        }

                        if (patch_offset > 255 && patch_offset <= 65535)
                        {
                            writer.Write(Middlebytes[1]);
                            writer.Write(Middlebytes[0]);
                        }
                        
                        if (patch_offset > 65535 && patch_offset <= 16777215)
                        {
                            writer.Write(Middlebytes[2]);
                            writer.Write(Middlebytes[1]);
                            writer.Write(Middlebytes[0]);
                        }
                        
                        if (patch_offset > 16777215)
                        {
                            writer.Write(Middlebytes[3]);
                            writer.Write(Middlebytes[2]);
                            writer.Write(Middlebytes[1]);
                            writer.Write(Middlebytes[0]);
                        }
                        
                        //end of stupid code
                        writer.Write(EndBytes);
                        richTextBox1.Text += "\n" + "IPS patch written";
                    }
                }
            }

            catch (Exception error)
            {
                MessageBox.Show("Error is: " + error.Message);
            }
        }

        private void FindloaderPatch()
        {
            try
            {
                int x;
                int y;
                byte[] ByteBuffer = File.ReadAllBytes("dec-loader.bin");
                byte[] StringBytes = new byte[8] { 0x01, 0xC0, 0xBE, 0x12, 0x1F, 0x00, 0x01, 0x6B };


                for (x = 0; x <= (ByteBuffer.Length - StringBytes.Length); x++)
                {
                    if (ByteBuffer[x] == StringBytes[0])
                    {
                        for (y = 1; y < StringBytes.Length && ByteBuffer[x + y] == StringBytes[y]; y++) ;
                        if (y == StringBytes.Length)
                            break;
                    }
                }

                patch_offset = (x + 6);
                string hex = patch_offset.ToString("X");

                richTextBox1.Text += "\n" + "Patch location: " + hex;
                //label_patch.Text = patchloc.ToString();

            }

            catch (Exception error)
            {
                MessageBox.Show("Error is: " + error.Message);
            }
        }

        private void Decrypt_loader()
        {
            try
            {
                Process process = new Process();
                process.StartInfo.FileName = "tools\\hactool.exe";
                process.StartInfo.Arguments = " --intype=kip1 --uncompressed=dec-loader.bin dumped_loader";
                process.StartInfo.UseShellExecute = false;
                process.StartInfo.CreateNoWindow = true;
                process.Start();
                process.WaitForExit(); //make sure hactool has completed the decryption.
                richTextBox1.Text += "\n" + "Loader decrypted";

                //we may as well remove the dumped loader here as it's not needed anymore
                if (checkBox_extracted.Checked)
                {
                    File.Delete("dumped_loader");
                    richTextBox1.Text += "\n" + "Extracted loader cleaned up";
                }
            }

            catch (Exception error)
            {
                MessageBox.Show("Error is: " + error.Message);
            }
        }

        private void Sha256()
        {
            try
            {
                using (SHA256 mySHA256 = SHA256.Create())
                {
                    using (BinaryReader read = new BinaryReader(new FileStream("dumped_loader", FileMode.Open)))
                    {
                        read.BaseStream.Position = 0;
                        byte[] hashValue = mySHA256.ComputeHash(read.BaseStream);
                        shaValue = String.Join("", hashValue.Select(x => x.ToString("X2")));
                        richTextBox1.Text += "\n" + "Sha256: " + shaValue;
                        //note - we should name our ips patch with the shaValue from above.
                    }
                }
            }

            catch (Exception error)
            {
                MessageBox.Show("Error is: " + error.Message);
            }
        }

        private static void AppendChunk(Stream output, Stream input, long start, long end)
        {
            long xsize = end - start;
            byte[] buffer = new byte[1 * 1024]; // Copy 1K at a time
            input.Position = start;
            while (xsize > 0)
            {
                int bytesRead = input.Read(buffer, 0, (int)Math.Min(xsize, buffer.Length));
                if (bytesRead <= 0)
                {
                    throw new EndOfStreamException("Not enough data");
                }
                output.Write(buffer, 0, bytesRead);
                xsize -= bytesRead;
            }
        }

Maybe that will be of some help for you.
 

dogcsty

Well-Known Member
Newcomer
Joined
Dec 2, 2021
Messages
47
Trophies
0
XP
227
Country
United States
Also @dogty - this is how the code looks in c# for doing the loader part (it might be easier to see what's going on here)

Code:
...

Maybe that will be of some help for you.
Thank you I appreciate it!
It would have been great if we were able to share a common library of the algorithms to capitalize on our workforce but it is what it is. I'll try to code the algorithms to be as platform independent as possible so it can be ported to pc if needed.
Thank you again for the help and the advice.
 

mrdude

Developer
Developer
Joined
Dec 11, 2015
Messages
3,071
Trophies
1
Age
56
XP
8,226
FYI, ES patch routines for the pc app are nearly done, I've tested from firmware 7.0 up to the latest 14.x and patches being generated are good, so just some minor stuff to do.

I still have FS and NIFM stuff to do (I didn't start those yet), however a lot of the code is the same as what was used to make the ES stuff and now I have wildcard searching done hopefully the app won't need many updates...

Here's a screenshot of the current progress:

6sSzUea.png


No ETA as I have a busy weekend and work this week, but it won't be too long.... :-)
 
Last edited by mrdude,

impeeza

¡Kabito!
Member
Joined
Apr 5, 2011
Messages
6,309
Trophies
3
Age
46
Location
At my chair.
XP
18,549
Country
Colombia
FYI, ES patch routines for the pc app are nearly done, I've tested from firmware 7.0 up to the latest 14.x and patches being generated are good, so just some minor stuff to do.

I still have FS and NIFM stuff to do (I didn't start those yet), however a lot of the code is the same as what was used to make the ES stuff and now I have wildcard searching done hopefully the app won't need many updates...

Here's a screenshot of the current progress:

6sSzUea.png


No ETA as I have a busy weekend and work this week, but it won't be too long.... :-)
Thanks for your work, get a good weekend and fun. You deserve
 

ZachyCatGames

Well-Known Member
Member
Joined
Jun 19, 2018
Messages
3,398
Trophies
1
Location
Hell
XP
4,208
Country
United States
Just to update you guys on what I'm working on. As some of you might know I'm working on a homebrew app allowing to directly generate the sigpatches from the switch.

I've successfully ported the hactool tool on the switch and I'm able to get the firmware files I need from the switch to generate the IPS.
Here is an example:


I've basically done the hard part which was finding the files of the current firmware and porting hactool (which was a mess btw I think I'm going to release a library for this so that people can play with it and manipulate ncas from the switch).

The only thing left for me to do is actually port the algorithm from python to C which shouldn't be too much of a trouble. I'm going to work on it in a week or two.

If you’re on hardware you can dump code for w/e stuff you’re patching from memory, or use ncm/fs commands to open/read whatever title(s) you need (this way you’d also need to impl pk21 parsing and nso/kip decompression, the former is dead simple, the latter I can’t imagine would be too bad). No need to port hactool.
 
Last edited by ZachyCatGames,

mrdude

Developer
Developer
Joined
Dec 11, 2015
Messages
3,071
Trophies
1
Age
56
XP
8,226
FYI, for those wishing to TEST the windows program for making patches (no need for python). I have now implemented ES IPS patch creation, this works the same as Alt-ES patch generation that is found in the python scripts. The reason I am posting this just now is for bug testing, as I may as well fix anything that crops up now before doing the NFIM and FS patch routines - alghough I imagine these will be easy to implement now if no major bugs are found.

Please report issues so I can fix them - note for ES patching, dragging and dropping is not implemented yet, just use the button to select your firmware folder.
 

impeeza

¡Kabito!
Member
Joined
Apr 5, 2011
Messages
6,309
Trophies
3
Age
46
Location
At my chair.
XP
18,549
Country
Colombia
FYI, for those wishing to TEST the windows program for making patches (no need for python). I have now implemented ES IPS patch creation, this works the same as Alt-ES patch generation that is found in the python scripts. The reason I am posting this just now is for bug testing, as I may as well fix anything that crops up now before doing the NFIM and FS patch routines - alghough I imagine these will be easy to implement now if no major bugs are found.

Please report issues so I can fix them - note for ES patching, dragging and dropping is not implemented yet, just use the button to select your firmware folder.
Buddy, tested with Atmosphère 0.10.0 to 1.03.2 and the patches created are O.K., then test firmwares 08.1.0 to 14.1.2 rebootless and the patches generated are exactly the same than Alternate ones.
A few tweaks:
  • On the Firmware folder selection dialog, could be good if you use the same dialog used for open file, that dialog can be parametrized to only select folders, will give you a consistent GUI. or also put the parameter on the current dialog to allow paste the path.
  • In the future you could put a menu item for importing Prod.Keys on to Keys.dat and/or Show/Editing existing one. (Like the one on NXNandManager)
  • In the future the Patches.ini file ¿Will be generated?.
@mrdude Thanks a lot for your hard work. I really want to know how to help on developing, but my programming skills stuck on Visual Basic :(

1660055575636.png
 
  • Like
Reactions: mrdude

impeeza

¡Kabito!
Member
Joined
Apr 5, 2011
Messages
6,309
Trophies
3
Age
46
Location
At my chair.
XP
18,549
Country
Colombia
FYI, for those wishing to TEST the windows program for making patches (no need for python). I have now implemented ES IPS patch creation, this works the same as Alt-ES patch generation that is found in the python scripts. The reason I am posting this just now is for bug testing, as I may as well fix anything that crops up now before doing the NFIM and FS patch routines - alghough I imagine these will be easy to implement now if no major bugs are found.

Please report issues so I can fix them - note for ES patching, dragging and dropping is not implemented yet, just use the button to select your firmware folder.
And other couple of observations:

On my tests, the "drag and drop" only works for Atmosphère file (package3 fuse-secondary.bin) and the triggering event is "hoover" on the app, not "drop" on the black and green text dialog.

So the process of file start when you hoover the file on to the app and do not wait to you "drop" the item, therefore when you drag a incorrect file (or folder) the message "File not supported" is popped before your let go the mouse click and if you try to get to the original program where you drag the object from, that program is lock waiting for IPS Patch Generator release the event, and the "file not supported" dialog is hidden behind all the current windows, so you have to find the dialog, click on OK to release the original program.
 
  • Like
Reactions: mrdude

mrdude

Developer
Developer
Joined
Dec 11, 2015
Messages
3,071
Trophies
1
Age
56
XP
8,226
@impeeza

Thanks for your comments, I will take note of them - also this is a test version so thanks for reporting. I noticed on visual studio 2022 that I am using that drag drop wasn't working so I needed to use drag over, which explains why there's issues, I've disabled that for now and will sort it out later. Graphics/Gui tweeks will come later as that basically just consists of dragging stuff about and very little coding is invovled. I was more looking for bugs on the coding side. If you find anymore stuff let me know. Also I will be putting this on github when I am done with it, so you will be able to mess about with the gui stuff and code soon as if you know visual basic, C# will be a breeze for you as it uses visual studio and coding wise it's easy to understand.

EDIT: Fixed drag drop for the loader patch, changed it to dropping on the Make PKG button instead and sorted the messagebox so it appears on top. You can redownload from the above attachment.
 
Last edited by mrdude,

impeeza

¡Kabito!
Member
Joined
Apr 5, 2011
Messages
6,309
Trophies
3
Age
46
Location
At my chair.
XP
18,549
Country
Colombia
@impeeza

Thanks for your comments, I will take note of them - also this is a test version so thanks for reporting. I noticed on visual studio 2022 that I am using that drag drop wasn't working so I needed to use drag over, which explains why there's issues, I've disabled that for now and will sort it out later. Graphics/Gui tweeks will come later as that basically just consists of dragging stuff about and very little coding is invovled. I was more looking for bugs on the coding side. If you find anymore stuff let me know. Also I will be putting this on github when I am done with it, so you will be able to mess about with the gui stuff and code soon as if you know visual basic, C# will be a breeze for you as it uses visual studio and coding wise it's easy to understand.

EDIT: Fixed drag drop for the loader patch, changed it to dropping on the Make PKG button instead and sorted the messagebox so it appears on top. You can redownload from the above attachment.
Thanks for you great work, reporting the Drag & Drop working fine for Atmosphère dropping on the "Make Patch" button
 

ZachyCatGames

Well-Known Member
Member
Joined
Jun 19, 2018
Messages
3,398
Trophies
1
Location
Hell
XP
4,208
Country
United States
dump code for w/e stuff you’re patching from memory
Wrote a rough impl of this b/c I'm bored, it'll dump text, rodata, data, and bss of w/e program you give it the programId for. The dump will be formatted like if you opened w/e program in ida
 

Attachments

  • source.7z
    1.5 KB · Views: 28

mrdude

Developer
Developer
Joined
Dec 11, 2015
Messages
3,071
Trophies
1
Age
56
XP
8,226
Thanks for you great work, reporting the Drag & Drop working fine for Atmosphère dropping on the "Make Patch" button
Thanks for letting me know, I also added FW folder dropping onto the Make Patch button on the ES page, so you can just drag your folder on to that button and it should make the patch. There's an updated zip in the post above.
 
  • Love
Reactions: impeeza

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
    BakerMan @ BakerMan: (cocks 12 gauge with virginity-maintaining intent) +1