diff --git a/NUS Downloader/Form1.Designer.cs b/NUS Downloader/Form1.Designer.cs index 4c5a548..aae886f 100644 --- a/NUS Downloader/Form1.Designer.cs +++ b/NUS Downloader/Form1.Designer.cs @@ -42,7 +42,6 @@ this.label1 = new System.Windows.Forms.Label(); this.label2 = new System.Windows.Forms.Label(); this.button2 = new System.Windows.Forms.Button(); - this.getcerts = new System.Windows.Forms.Button(); this.wadnamebox = new System.Windows.Forms.TextBox(); this.ignoreticket = new System.Windows.Forms.CheckBox(); this.decryptbox = new System.Windows.Forms.CheckBox(); @@ -245,18 +244,6 @@ this.button2.UseVisualStyleBackColor = true; this.button2.Click += new System.EventHandler(this.button2_Click); // - // getcerts - // - this.getcerts.BackColor = System.Drawing.Color.Bisque; - this.getcerts.FlatStyle = System.Windows.Forms.FlatStyle.Popup; - this.getcerts.Location = new System.Drawing.Point(48, 246); - this.getcerts.Name = "getcerts"; - this.getcerts.Size = new System.Drawing.Size(176, 46); - this.getcerts.TabIndex = 16; - this.getcerts.Text = "Generate Certs"; - this.getcerts.UseVisualStyleBackColor = false; - this.getcerts.Click += new System.EventHandler(this.getcerts_Click); - // // wadnamebox // this.wadnamebox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; @@ -757,9 +744,9 @@ this.contentModBox.Controls.Add(this.button11); this.contentModBox.Controls.Add(this.button9); this.contentModBox.Controls.Add(this.button10); - this.contentModBox.Location = new System.Drawing.Point(268, 153); + this.contentModBox.Location = new System.Drawing.Point(278, 434); this.contentModBox.Name = "contentModBox"; - this.contentModBox.Size = new System.Drawing.Size(249, 327); + this.contentModBox.Size = new System.Drawing.Size(249, 69); this.contentModBox.TabIndex = 41; this.contentModBox.TabStop = false; this.contentModBox.Text = "Edit Title Contents"; @@ -907,7 +894,7 @@ this.toolStripSeparator3, this.emulateUpdate}); this.extrasStrip.Name = "extrasStrip"; - this.extrasStrip.Size = new System.Drawing.Size(220, 76); + this.extrasStrip.Size = new System.Drawing.Size(220, 54); // // loadInfoFromTMDToolStripMenuItem // @@ -965,18 +952,17 @@ this.Controls.Add(this.button3); this.Controls.Add(this.shamelessvariablelabel); this.Controls.Add(this.button1); - this.Controls.Add(this.contentModBox); this.Controls.Add(this.button17); this.Controls.Add(this.ticketgpbox); this.Controls.Add(this.tmdgpbox); this.Controls.Add(this.truchabox); this.Controls.Add(this.databaseButton); this.Controls.Add(this.button5); + this.Controls.Add(this.contentModBox); this.Controls.Add(this.button4); this.Controls.Add(this.decryptbox); this.Controls.Add(this.ignoreticket); this.Controls.Add(this.wadnamebox); - this.Controls.Add(this.getcerts); this.Controls.Add(this.button7); this.Controls.Add(this.label2); this.Controls.Add(this.titleversion); @@ -1028,7 +1014,6 @@ private System.Windows.Forms.RadioButton radioButton1; private System.Windows.Forms.RadioButton radioButton2; private System.Windows.Forms.Button button2; - private System.Windows.Forms.Button getcerts; private System.Windows.Forms.TextBox wadnamebox; private System.Windows.Forms.CheckBox ignoreticket; private System.Windows.Forms.CheckBox decryptbox; diff --git a/NUS Downloader/Form1.cs b/NUS Downloader/Form1.cs index 167e089..3acf011 100644 --- a/NUS Downloader/Form1.cs +++ b/NUS Downloader/Form1.cs @@ -31,6 +31,17 @@ namespace NUS_Downloader Image redgreen = Properties.Resources.bullet_redgreen; Image redorange = Properties.Resources.bullet_redorange; + // Certs storage + byte[] cert_CA = new byte[0x400]; + byte[] cert_CACP = new byte[0x300]; + byte[] cert_CAXS = new byte[0x300]; + + byte[] cert_CA_sha1 = new byte[20] {0x5B, 0x7D, 0x3E, 0xE2, 0x87, 0x06, 0xAD, 0x8D, 0xA2, 0xCB, 0xD5, 0xA6, 0xB7, 0x5C, 0x15, 0xD0, 0xF9, 0xB6, 0xF3, 0x18}; + byte[] cert_CACP_sha1 = new byte[20] {0x68, 0x24, 0xD6, 0xDA, 0x4C, 0x25, 0x18, 0x4F, 0x0D, 0x6D, 0xAF, 0x6E, 0xDB, 0x9C, 0x0F, 0xC5, 0x75, 0x22, 0xA4, 0x1C}; + byte[] cert_CAXS_sha1 = new byte[20] {0x09, 0x78, 0x70, 0x45, 0x03, 0x71, 0x21, 0x47, 0x78, 0x24, 0xBC, 0x6A, 0x3E, 0x5E, 0x07, 0x61, 0x56, 0x57, 0x3F, 0x8A}; + + byte[] cert_total_sha1 = new byte[20] {0xAC, 0xE0, 0xF1, 0x5D, 0x2A, 0x85, 0x1C, 0x38, 0x3F, 0xE4, 0x65, 0x7A, 0xFC, 0x38, 0x40, 0xD6, 0xFF, 0xE3, 0x0A, 0xD0}; + public struct WADHeader { public int HeaderSize; @@ -67,6 +78,7 @@ namespace NUS_Downloader public Form1(string[] args) { InitializeComponent(); + Application.DoEvents(); // certs.sys / key.bin if (BootChecks() == false) @@ -144,8 +156,8 @@ namespace NUS_Downloader // Close if specified while (NUSDownloader.IsBusy) - { - // Do nothing... + { + Thread.Sleep(1000); } if ((NUSDownloader.IsBusy == false) && (endafter == true)) { @@ -169,7 +181,7 @@ namespace NUS_Downloader if (currentdir.EndsWith(Convert.ToString(Path.DirectorySeparatorChar)) == false) currentdir += Path.DirectorySeparatorChar; - // Check for certs file + /* Check for certs file if (File.Exists(currentdir + "cert.sys") == false) { foreach (Control ctrl in this.Controls) @@ -194,7 +206,7 @@ namespace NUS_Downloader { getcerts.Visible = false; WriteStatus("Certs file is present and intact."); - } + }*/ // Check for Wii common key bin file... if (File.Exists(currentdir + "key.bin") == false) @@ -728,13 +740,13 @@ namespace NUS_Downloader downloadstartbtn.Text = "Prerequisites: (2/2)"; dlprogress.Value = 100; + // Create ticket file holder + byte[] cetkbuf = FileLocationToByteArray(titledirectory + @"\cetk"); + // Obtain TitleKey byte[] titlekey = new byte[16]; if (decryptbox.Checked == true) { - // Create ticket file holder - byte[] cetkbuf = FileLocationToByteArray(titledirectory + @"\cetk"); - // Load TitleKey into it's byte[] // It is currently encrypted... for (int i = 0; i < 16; i++) @@ -778,6 +790,17 @@ namespace NUS_Downloader // Read the tmd as a stream... byte[] tmd = FileLocationToByteArray(titledirectory + tmdfull); + // Locate Certs ************************************** + if (!(CertsValid())) + { + WriteStatus("Searching for certs..."); + ScanForCerts(tmd); + ScanForCerts(cetkbuf); + } + else + WriteStatus("Using cached certs..."); + // /Locate Cert ************************************** + // Read Title Version... string tmdversion = ""; for (int x = 476; x < 478; x++) @@ -859,9 +882,6 @@ namespace NUS_Downloader // Create content file holder byte[] contbuf = FileLocationToByteArray(titledirectory + @"\" + tmdcontents[i]); - // Create ticket file holder - byte[] cetkbuf = FileLocationToByteArray(titledirectory + @"\cetk"); - // IV (00+IDX+more000) byte[] iv = new byte[16]; for (int x = 0; x < 16; x++) @@ -927,13 +947,10 @@ namespace NUS_Downloader requiredIOSbox.Enabled = true; // Read information from TIK into signing GUI... - // Create ticket file holder - byte[] cetkbuff = FileLocationToByteArray(titledirectory + @"\cetk"); - // Titlekey for (int i = 0; i < 16; i++) { - titlekey[i] = cetkbuff[0x1BF + i]; + titlekey[i] = cetkbuf[0x1BF + i]; } //titlekeybox.Text = DisplayBytes(titlekey).Replace(" ", ""); titlekeybox.Text = System.Text.Encoding.UTF7.GetString(titlekey); @@ -942,7 +959,7 @@ namespace NUS_Downloader byte[] iv = new byte[16]; for (int i = 0; i < 8; i++) { - iv[i] = cetkbuff[0x1DC + i]; + iv[i] = cetkbuf[0x1DC + i]; } for (int i = 0; i < 8; i++) { @@ -951,20 +968,20 @@ namespace NUS_Downloader titleIDIV.Text = DisplayBytes(iv, ""); //DLC - dlcamntbox.Text = Convert.ToString((cetkbuff[0x1E6]*256) + cetkbuff[0x1E7]); + dlcamntbox.Text = Convert.ToString((cetkbuf[0x1E6]*256) + cetkbuf[0x1E7]); //keyindex - if (cetkbuff[0x1F1] == 0x00) + if (cetkbuf[0x1F1] == 0x00) ckeyindexcb.SelectedIndex = 0; - else if (cetkbuff[0x1F1] == 0x01) + else if (cetkbuf[0x1F1] == 0x01) ckeyindexcb.SelectedIndex = 1; else ckeyindexcb.SelectedIndex = 0; //time enabled - if (cetkbuff[0x247] == 0x00) + if (cetkbuf[0x247] == 0x00) timelimitenabledcb.SelectedIndex = 0; - else if (cetkbuff[0x247] == 0x01) + else if (cetkbuf[0x247] == 0x01) timelimitenabledcb.SelectedIndex = 1; else timelimitenabledcb.SelectedIndex = 0; @@ -973,7 +990,7 @@ namespace NUS_Downloader byte[] timelimit = new byte[4]; for (int i = 0; i < timelimit.Length; i++) { - timelimit[i] = cetkbuff[0x248 + 1]; + timelimit[i] = cetkbuf[0x248 + 1]; } timelimitsecs.Text = Convert.ToString(System.BitConverter.ToInt32(timelimit, 0)); @@ -1103,13 +1120,37 @@ namespace NUS_Downloader public void PackWAD(string titleid, string tmdfilename, int contentcount, string[] contentnames, string[] contentsizes, string totaldirectory) { + WriteStatus("Beginning WAD Pack..."); // Directory stuff string currentdir = Application.StartupPath; if (!(currentdir.EndsWith(@"\")) || !(currentdir.EndsWith(@"/"))) currentdir += @"\"; // Create cert file holder - byte[] certsbuf = FileLocationToByteArray(currentdir + @"\cert.sys"); + //byte[] certsbuf = FileLocationToByteArray(currentdir + @"\cert.sys"); + byte[] certsbuf = new byte[0xA00]; + if (!(CertsValid())) + { + WriteStatus("Error: NUSD could not locate cached certs!"); + return; + } + for (int c = 0; c < cert_CA.Length; c++) + { + certsbuf[c] = cert_CA[c]; + } + for (int c = 0; c < cert_CACP.Length; c++) + { + certsbuf[c + 0x400] = cert_CACP[c]; + } + for (int c = 0; c < cert_CAXS.Length; c++) + { + certsbuf[c + 0x700] = cert_CAXS[c]; + } + if (!(TotalCertValid(certsbuf))) + { + WriteStatus("Error: Cert array did not hash properly!"); + return; + } // Create ticket file holder byte[] cetkbuf = FileLocationToByteArray(totaldirectory + @"\cetk"); @@ -1132,7 +1173,7 @@ namespace NUS_Downloader // Write cert[] to 0x40. wadfs.Seek(0x40, SeekOrigin.Begin); wadfs.Write(certsbuf, 0, certsbuf.Length); - WriteStatus("Cert wrote (0x" + Convert.ToString(64, 16) + ")"); + WriteStatus(" - Certs wrote (0x" + Convert.ToString(64, 16) + ")"); // Need 64 byte boundary... wadfs.Seek(2624, SeekOrigin.Begin); @@ -1141,7 +1182,7 @@ namespace NUS_Downloader // Write ticket at this point... wad.TicketSize = 0x2A4; wadfs.Write(cetkbuf, 0, wad.TicketSize); - WriteStatus("Ticket wrote (0x" + Convert.ToString((wadfs.Length - 0x2A4), 16) + ")"); + WriteStatus(" - Ticket wrote (0x" + Convert.ToString((wadfs.Length - 0x2A4), 16) + ")"); // Need 64 byte boundary... wadfs.Seek(ByteBoundary(Convert.ToInt32(wadfs.Length)), SeekOrigin.Begin); @@ -1149,7 +1190,7 @@ namespace NUS_Downloader // Write TMD at this point... wad.TMDSize = 484 + (contentcount * 36); wadfs.Write(tmdbuf, 0, 484 + (contentcount * 36)); - WriteStatus("TMD wrote (0x" + Convert.ToString((wadfs.Length - (484 + (contentcount * 36))), 16) + ")"); + WriteStatus(" - TMD wrote (0x" + Convert.ToString((wadfs.Length - (484 + (contentcount * 36))), 16) + ")"); // Preliminary data size of wad file. wad.DataSize = 0; @@ -1165,7 +1206,7 @@ namespace NUS_Downloader wadfs.Write(contbuf, 0, contbuf.Length); - WriteStatus(contentnames[i] + " wrote (0x" + Convert.ToString((wadfs.Length - contbuf.Length), 16) + ")"); + WriteStatus(" - " + contentnames[i] + " wrote (0x" + Convert.ToString((wadfs.Length - contbuf.Length), 16) + ")"); HandleMismatch(int.Parse(contentsizes[i], System.Globalization.NumberStyles.HexNumber), contbuf.Length); wad.DataSize += contbuf.Length; @@ -1319,7 +1360,7 @@ namespace NUS_Downloader private void getcerts_Click(object sender, EventArgs e) { // Get a certs.sys from NUS... - + /* // Directory stuff string currentdir = Application.StartupPath; if (currentdir.EndsWith(Convert.ToString(Path.DirectorySeparatorChar)) == false) @@ -1376,8 +1417,9 @@ namespace NUS_Downloader // Cleanup... File.Delete(currentdir + "cetk"); File.Delete(currentdir + "tmd.289"); + */ } - + /* static string getMd5Hash(string input) { System.Text.StringBuilder sb = new System.Text.StringBuilder(); @@ -1412,7 +1454,7 @@ namespace NUS_Downloader return false; } } - + */ private void packbox_CheckedChanged(object sender, EventArgs e) { if (packbox.Checked == true) @@ -3332,5 +3374,83 @@ namespace NUS_Downloader WriteStatus(String.Format("{0}v{1}", TitleID, Version)); } } + + private void ScanForCerts(byte[] tmdortik) + { + + // For some reason a few 00s are cut off, so pad it up to be safe. + tmdortik = PadToMultipleOf(tmdortik, 16); + + // Search for cert_CACP + if (!(tmdortik.Length < 0x300)) + for (int a = 0; a < (tmdortik.Length - 0x300); a++) + { + byte[] chunk = new byte[0x300]; + for (int b = 0; b < 0x300; b++) + { + chunk[b] = tmdortik[a + b]; + } + if (Convert.ToBase64String(ComputeSHA(chunk)) == Convert.ToBase64String(cert_CACP_sha1)) + { + cert_CACP = chunk; + WriteStatus(" - Cert CA-CP Located!"); + break; + } + } + + // Search for cert_CAXS + if (!(tmdortik.Length < 0x300)) + for (int a = 0; a < (tmdortik.Length - 0x300); a++) + { + byte[] chunk = new byte[0x300]; + for (int b = 0; b < 0x300; b++) + { + chunk[b] = tmdortik[a + b]; + } + if (Convert.ToBase64String(ComputeSHA(chunk)) == Convert.ToBase64String(cert_CAXS_sha1)) + { + cert_CAXS = chunk; + WriteStatus(" - Cert CA-XS Located!"); + break; + } + } + + // Search for cert_CA + if ((!(tmdortik.Length < 0x400)) && ((Convert.ToBase64String(cert_CA) != Convert.ToBase64String(cert_CA_sha1)))) + { + for (int a = 0; a < (tmdortik.Length - 0x400); a++) + { + byte[] chunk = new byte[0x400]; + for (int b = 0; b < 0x400; b++) + { + chunk[b] = tmdortik[a + b]; + } + if (Convert.ToBase64String(ComputeSHA(chunk)) == Convert.ToBase64String(cert_CA_sha1)) + { + cert_CA = chunk; + WriteStatus(" - Cert CA Located!"); + break; + } + } + } + } + + private bool CertsValid() + { + if (Convert.ToBase64String(ComputeSHA(cert_CA)) != Convert.ToBase64String(cert_CA_sha1)) + return false; + if (Convert.ToBase64String(ComputeSHA(cert_CACP)) != Convert.ToBase64String(cert_CACP_sha1)) + return false; + if (Convert.ToBase64String(ComputeSHA(cert_CAXS)) != Convert.ToBase64String(cert_CAXS_sha1)) + return false; + return true; + } + + private bool TotalCertValid(byte[] cert_sys) + { + if (Convert.ToBase64String(ComputeSHA(cert_sys)) != Convert.ToBase64String(cert_total_sha1)) + return false; + return true; + } } } diff --git a/NUS Downloader/NUS Downloader.csproj b/NUS Downloader/NUS Downloader.csproj index 3da25d4..dbbdd8e 100644 --- a/NUS Downloader/NUS Downloader.csproj +++ b/NUS Downloader/NUS Downloader.csproj @@ -16,7 +16,7 @@ false 5828AACDBD1A48E3768B7E0465E90D0E96E2BE4C NUS Downloader_TemporaryKey.pfx - true + false true LocalIntranet Properties\app.manifest diff --git a/NUS Downloader/Properties/app.manifest b/NUS Downloader/Properties/app.manifest index 70f40fe..c68a6a2 100644 --- a/NUS Downloader/Properties/app.manifest +++ b/NUS Downloader/Properties/app.manifest @@ -18,8 +18,8 @@ - +