diff --git a/NUS Downloader/Form1.Designer.cs b/NUS Downloader/Form1.Designer.cs index 1482b8f..abf6e7d 100644 --- a/NUS Downloader/Form1.Designer.cs +++ b/NUS Downloader/Form1.Designer.cs @@ -67,6 +67,7 @@ this.WiiWareMenuList = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); this.RegionCodesList = new System.Windows.Forms.ToolStripMenuItem(); + this.truchabox = new System.Windows.Forms.CheckBox(); this.databaseStrip.SuspendLayout(); this.SuspendLayout(); // @@ -151,9 +152,9 @@ this.localuse.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.localuse.Location = new System.Drawing.Point(12, 468); this.localuse.Name = "localuse"; - this.localuse.Size = new System.Drawing.Size(175, 17); + this.localuse.Size = new System.Drawing.Size(167, 17); this.localuse.TabIndex = 8; - this.localuse.Text = "Use/Keep Local Files if Present"; + this.localuse.Text = "Use/Keep Present Local Files"; this.localuse.UseVisualStyleBackColor = true; // // NUSDownloader @@ -222,9 +223,9 @@ // this.button2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.button2.FlatStyle = System.Windows.Forms.FlatStyle.Popup; - this.button2.Location = new System.Drawing.Point(193, 465); + this.button2.Location = new System.Drawing.Point(184, 390); this.button2.Name = "button2"; - this.button2.Size = new System.Drawing.Size(69, 20); + this.button2.Size = new System.Drawing.Size(78, 20); this.button2.TabIndex = 14; this.button2.Text = "About"; this.button2.UseVisualStyleBackColor = true; @@ -419,18 +420,30 @@ this.RegionCodesList.Text = "Region Codes"; this.RegionCodesList.DropDownItemClicked += new System.Windows.Forms.ToolStripItemClickedEventHandler(this.RegionCodesList_DropDownItemClicked); // + // truchabox + // + this.truchabox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.truchabox.AutoSize = true; + this.truchabox.Location = new System.Drawing.Point(184, 468); + this.truchabox.Name = "truchabox"; + this.truchabox.Size = new System.Drawing.Size(60, 17); + this.truchabox.TabIndex = 21; + this.truchabox.Text = "Trucha"; + this.truchabox.UseVisualStyleBackColor = true; + // // Form1 // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(274, 496); + this.Controls.Add(this.truchabox); this.Controls.Add(this.databaseButton); this.Controls.Add(this.decryptbox); this.Controls.Add(this.ignoreticket); this.Controls.Add(this.wadnamebox); this.Controls.Add(this.getcerts); - this.Controls.Add(this.button2); this.Controls.Add(this.label2); + this.Controls.Add(this.button2); this.Controls.Add(this.titleversion); this.Controls.Add(this.label1); this.Controls.Add(this.radioButton1); @@ -492,6 +505,7 @@ private System.Windows.Forms.ToolStripMenuItem TurboGrafxCDMenuList; private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; private System.Windows.Forms.ToolStripMenuItem RegionCodesList; + private System.Windows.Forms.CheckBox truchabox; } } diff --git a/NUS Downloader/Form1.cs b/NUS Downloader/Form1.cs index bddd056..afaa165 100644 --- a/NUS Downloader/Form1.cs +++ b/NUS Downloader/Form1.cs @@ -685,6 +685,7 @@ namespace NUS_Downloader // Read the tmd as a stream... FileStream fs = File.OpenRead(titledirectory + tmdfull); byte[] tmd = ReadFully(fs, 20); + fs.Close(); // Read Title Version... string tmdversion = ""; @@ -817,6 +818,34 @@ namespace NUS_Downloader WriteStatus("NUS Download Finished."); + // Trucha signing... + if ((truchabox.Checked == true) && (wiimode == true)) + { + WriteStatus("Trucha Signing TMD..."); + Array.Resize(ref tmd, 484 + (Convert.ToInt32(contentstrnum) * 36)); + tmd = ZeroSignature(tmd); + tmd = TruchaSign(tmd); + + FileStream testtmd = new FileStream(titledirectory + tmdfull, FileMode.Open); + testtmd.Write(tmd, 0, tmd.Length); + testtmd.Close(); + + WriteStatus("Trucha Signing Ticket..."); + + // Create ticket file holder + FileStream cetkf = File.OpenRead(titledirectory + @"\cetk"); + byte[] cetkbuff = ReadFully(cetkf, 20); + cetkf.Close(); + + Array.Resize(ref cetkbuff, 0x2A4); + cetkbuff = ZeroSignature(cetkbuff); + cetkbuff = TruchaSign(cetkbuff); + + FileStream testtik = new FileStream(titledirectory + "cetk", FileMode.Open); + testtik.Write(cetkbuff, 0, cetkbuff.Length); + testtik.Close(); + } + if ((packbox.Checked == true) && (wiimode == true)) { PackWAD(titleid, tmdfull, tmdcontents.Length, tmdcontents, tmdsizes, titledirectory); @@ -935,11 +964,6 @@ namespace NUS_Downloader wad.WadType = 0x49730000; wad.CertChainSize = 0xA00; - // TMDSize is length of buffer. - wad.TMDSize = tmdbuf.Length; - // TicketSize is length of cetkbuf. - wad.TicketSize = cetkbuf.Length; - // Write cert[] to 0x40. wadfs.Seek(0x40, SeekOrigin.Begin); wadfs.Write(certsbuf, 0, certsbuf.Length); @@ -958,6 +982,7 @@ namespace NUS_Downloader wadfs.Seek(ByteBoundary(Convert.ToInt32(wadfs.Length)), SeekOrigin.Begin); // 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) + ")"); @@ -1700,5 +1725,67 @@ namespace NUS_Downloader if (titleidbox.Text.Length == 16) titleidbox.Text = titleidbox.Text.Substring(0, 14) + e.ClickedItem.Text.Substring(0, 2); } + + private byte[] ZeroSignature(byte[] tmdortik) + { + // Write all 0x00 to signature... + // Sig starts at 0x04 in both TMD/TIK + for (int i = 0; i < 256; i++) + { + tmdortik[i + 4] = 0x00; + } + + WriteStatus(" - Signature Emptied..."); + return tmdortik; + } + + private byte[] TruchaSign(byte[] tmdortik) + { + // Loop through 2 bytes worth of numbers until hash starts with 0x00... + // Padding starts at 0x104 in both TMD/TIK, seems like a good place to me... + + byte[] payload = new byte[2]; + byte[] hashobject = new byte[tmdortik.Length - 0x104]; + + for (int i = 0; i < 65535; i++) + { + payload = incrementAtIndex(payload, 1); + + tmdortik[0x104] = payload[0]; + tmdortik[0x105] = payload[1]; + + for (int x = 0; x < (tmdortik.Length - 0x104); x++) + { + hashobject[x] = tmdortik[0x104 + x]; + } + + if (ComputeSHA(hashobject)[0] == 0x00) + { + // DEBUG: + //WriteStatus(DisplayBytes(ComputeSHA(hashobject))); + WriteStatus(" - Successfully Trucha Signed."); + return tmdortik; + } + } + + WriteStatus(" - Sign FAIL!"); + return tmdortik; + } + + static public byte[] incrementAtIndex(byte[] array, int index) + { + if (array[index] == byte.MaxValue) + { + array[index] = 0; + if (index > 0) + incrementAtIndex(array, index - 1); + } + else + { + array[index]++; + } + + return array; + } } }