Initial attempt at decoding Wi-fi Plaza gamestats blobs

This commit is contained in:
Greg Edwards 2014-05-20 12:15:15 -04:00
parent 1d931ff91b
commit 1eab40f4a1
5 changed files with 129 additions and 1 deletions

View File

@ -89,6 +89,7 @@
<Compile Include="BattleVideo.aspx.designer.cs">
<DependentUpon>BattleVideo.aspx</DependentUpon>
</Compile>
<Compile Include="src\GamestatsSessionPlat.cs" />
<Compile Include="src\HeaderColour.cs" />
<Compile Include="test\BoxUp.aspx.cs">
<DependentUpon>BoxUp.aspx</DependentUpon>

View File

@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Security.Cryptography;
using System.IO;
using System.Net;
namespace PkmnFoundations.GTS
{
public class GamestatsSessionPlat : GtsSessionBase
{
public GamestatsSessionPlat(int pid, String url)
: base(pid, url)
{
Hash = ComputeHash(Token);
}
public static String ComputeHash(String token)
{
// todo: add unit tests with some wiresharked examples.
if (m_sha1 == null) m_sha1 = SHA1.Create();
String longToken = "uLMOGEiiJogofchScpXb" + token;
byte[] data = new byte[longToken.Length];
MemoryStream stream = new MemoryStream(data);
StreamWriter writer = new StreamWriter(stream);
writer.Write(longToken); // fixme: this throws an OutOfBoundsException if the passed token contains non-ascii.
writer.Flush();
return m_sha1.ComputeHash(data).ToHexStringLower();
}
/// <summary>
/// Decrypts the NDS &data= querystring into readable binary data.
/// The PID (little endian) is left at the start of the output
/// but the (unencrypted) checksum is removed.
/// </summary>
public static byte[] DecryptData(String data)
{
byte[] data2 = FromUrlSafeBase64String(data);
if (data2.Length < 4) throw new FormatException("Data must contain at least 4 bytes.");
byte[] data3 = new byte[data2.Length - 4];
int checksum = BitConverter.ToInt32(data2, 0);
checksum = IPAddress.NetworkToHostOrder(checksum); // endian flip
checksum ^= 0x5b440000;
int rand = checksum | (checksum << 16);
// todo: prune first 8 bytes, pass pid to this function to validate
for (int pos = 0; pos < data3.Length; pos++)
{
rand = DecryptRNG(rand);
data3[pos] = (byte)(data2[pos + 4] ^ (byte)(rand >> 16));
}
int checkedsum = 0;
foreach (byte b in data3)
checkedsum += b;
if (checkedsum != checksum) throw new FormatException("Data checksum is incorrect.");
return data3;
}
}
}

View File

@ -17,6 +17,11 @@
<div class="code">
<asp:Literal ID="litDecoded" runat="server" />
</div>
<asp:PlaceHolder ID="phChecksum" Visible="false" runat="server">
<p>
Checksum: <asp:Literal ID="litChecksum" runat="server" />
</p>
</asp:PlaceHolder>
</div>
</asp:PlaceHolder>
</form>

View File

@ -5,6 +5,7 @@ using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Text;
using System.Net;
namespace PkmnFoundations.GTS.debug
{
@ -13,12 +14,14 @@ namespace PkmnFoundations.GTS.debug
protected void Page_Load(object sender, EventArgs e)
{
litMessage.Text = "";
litChecksum.Text = "";
}
protected void btnDecode_Click(object sender, EventArgs e)
{
byte[] data = null;
phDecoded.Visible = false;
phChecksum.Visible = false;
try
{
@ -38,16 +41,49 @@ namespace PkmnFoundations.GTS.debug
{
}
if (data == null) try
{
data = GamestatsSessionPlat.DecryptData(txtData.Text);
litGeneration.Text = "Platinum";
}
catch (FormatException)
{
}
if (data == null)
{
data = DecryptData(txtData.Text);
int checkedsum = 0;
foreach (byte b in data)
checkedsum += b;
litGeneration.Text = "";
litChecksum.Text = checkedsum.ToString();
phChecksum.Visible = true;
}
if (data == null)
{
litMessage.Text = "<p class=\"errorMessage\">Data is not formatted correctly.</p>";
return;
}
litDecoded.Text = RenderHex(data.ToHexStringLower());
phDecoded.Visible = true;
}
public static byte[] DecryptData(String data)
{
byte[] data2 = GtsSessionBase.FromUrlSafeBase64String(data);
if (data2.Length < 12) throw new FormatException("Data must contain at least 12 bytes.");
int checksum = BitConverter.ToInt32(data2, 0);
checksum = IPAddress.NetworkToHostOrder(checksum); // endian flip
//checksum ^= 0x2db842b2;
return data2;
}
private String RenderHex(String hex)
{
StringBuilder builder = new StringBuilder();

View File

@ -74,5 +74,23 @@ namespace PkmnFoundations.GTS.debug {
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.Literal litDecoded;
/// <summary>
/// phChecksum control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.PlaceHolder phChecksum;
/// <summary>
/// litChecksum control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.Literal litChecksum;
}
}