Skip to content

Commit

Permalink
Fixed Steam path bug and added in profile rehashing code
Browse files Browse the repository at this point in the history
  • Loading branch information
John committed Apr 1, 2020
1 parent 6d26fef commit c071bec
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 48 deletions.
98 changes: 96 additions & 2 deletions Crypto.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@ namespace DOOMSaveManager
{
public static class Crypto
{
public static byte[] EncryptAndDigest(string aad, byte[] data) {
private const uint C1 = 0xCC9E2D51;
private const uint C2 = 0x1B873593;
private const uint C3 = 0xE6546B64;

public static uint rotr(uint n, int d) => (n >> d) | (n << (32 - d));

public static byte[] EncryptAndDigest(string aad, byte[] data) {
byte[] nonce = Utilities.RandomBytes(12);
byte[] aadBytes = Encoding.UTF8.GetBytes(aad);
byte[] aadHash = new SHA256Managed().ComputeHash(aadBytes);
Expand Down Expand Up @@ -45,5 +51,93 @@ public static byte[] DecryptAndVerify(string aad, byte[] data) {

return plaintext;
}
}

public static byte[] CalcProfileHash(byte[] data) {
byte[] pfData = new byte[data.Length - 0xC];
Buffer.BlockCopy(data, 0xC, pfData, 0, pfData.Length);

return FarmHash_Hash32(pfData);
}

public static uint Mur(uint a, uint h) {
// Taken from https://github.com/google/farmhash/blob/master/src/farmhash.cc

a *= C1;
a = rotr(a, 17);
a *= C2;
h ^= a;
h = rotr(h, 19);

return h * 5 + C3;
}

public static byte[] FarmHash_Hash32(byte[] data) {
// Taken from https://github.com/google/farmhash/blob/master/src/farmhash.cc

uint size = (uint)data.Length;

uint h = size;
uint g = C1 * size;
uint f = g;

uint a0 = rotr(BitConverter.ToUInt32(data, (int)(size - 4)) * C1, 17) * C2;
uint a1 = rotr(BitConverter.ToUInt32(data, (int)(size - 8)) * C1, 17) * C2;
uint a2 = rotr(BitConverter.ToUInt32(data, (int)(size - 12)) * C1, 17) * C2;
uint a3 = rotr(BitConverter.ToUInt32(data, (int)(size - 16)) * C1, 17) * C2;
uint a4 = rotr(BitConverter.ToUInt32(data, (int)(size - 20)) * C1, 17) * C2;

h ^= a0;
h = rotr(h, 19);
h = h * 5 + C3;
h ^= a3;
h = rotr(h, 19);
h = h * 5 + C3;

g ^= a1;
g = rotr(g, 19);
g = g * 5 + C3;
g ^= a2;
g = rotr(g, 19);
g = g * 5 + C3;

f += a4;
f = rotr(f, 19) + 113;

uint iters = (size - 1) / 20;

uint s = 0;
do {
uint a = BitConverter.ToUInt32(data, (int)s);
uint b = BitConverter.ToUInt32(data, (int)s + 4);
uint c = BitConverter.ToUInt32(data, (int)s + 8);
uint d = BitConverter.ToUInt32(data, (int)s + 12);
uint e = BitConverter.ToUInt32(data, (int)s + 16);
h += a;
g += b;
f += c;
h = Mur(d, h) + e;
g = Mur(c, g) + a;
f = Mur(b + e * C1, f) + d;
f += g;
g += f;
s += 20;
} while (--iters != 0);

g = rotr(g, 11) * C1;
g = rotr(g, 17) * C1;
f = rotr(f, 11) * C1;
f = rotr(f, 17) * C1;
h = rotr(h + g, 19);
h = h * 5 + C3;
h = rotr(h, 17) * C1;
h = rotr(h + f, 19);
h = h * 5 + C3;
h = rotr(h, 17) * C1;

byte[] r = BitConverter.GetBytes(h);
Array.Reverse(r);

return r;
}
}
}
43 changes: 4 additions & 39 deletions DoomEternal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
using System.IO;
using System.Collections.Generic;
using System.Reflection.Emit;
using Org.BouncyCastle.Cms;
using Org.BouncyCastle.Crypto.Engines;

namespace DOOMSaveManager
{
Expand All @@ -19,13 +21,15 @@ public class DoomEternal

public static void EnumerateSaves() {
Saves = new DoomEternalSavePathCollection();

if (Directory.Exists(BnetSavePath)) {
Saves.Add(new DoomEternalSavePath("savegame.unencrypted", DoomEternalSavePlatform.BethesdaNet, false));
foreach (var single in Directory.GetDirectories(BnetSavePath, "*.*", SearchOption.TopDirectoryOnly)) {
if (Utilities.CheckUUID(Path.GetFileNameWithoutExtension(single)))
Saves.Add(new DoomEternalSavePath(Path.GetFileNameWithoutExtension(single), DoomEternalSavePlatform.BethesdaNet));
}
}

if (Directory.Exists(SteamSavePath)) {
foreach (var steamId3 in Directory.GetDirectories(SteamSavePath, "*.*", SearchOption.TopDirectoryOnly)) {
foreach (var single in Directory.GetDirectories(steamId3, "*.*", SearchOption.TopDirectoryOnly)) {
Expand All @@ -35,44 +39,5 @@ public static void EnumerateSaves() {
}
}
}

public static byte[] FarmHash_Hash32(byte[] data) {
uint size = (uint)data.Length;
if (size > 0x18) {
uint v3 = 5 * (Utilities.rotl(0x1B873593 * Utilities.rotl(0xCC9E2D51 * BitConverter.ToUInt32(data, (int)(size - 0x10)), 0xF) ^ 5 * (Utilities.rotl(size ^ 0x1B873593 * Utilities.rotl(0xCC9E2D51 * BitConverter.ToUInt32(data, (int)(size - 4)), 0xF), 0xD) - 0x52250EC), 0xD) - 0x52250EC);
uint v4 = 5 * (Utilities.rotl(0x1B873593 * Utilities.rotl(0xCC9E2D51 * BitConverter.ToUInt32(data, (int)(size - 0xC)), 0xF) ^ 5 * (Utilities.rotl(0xCC9E2D51 * size ^ 0x1B873593 * Utilities.rotl(0xCC9E2D51 * BitConverter.ToUInt32(data, (int)(size - 8)), 0xF), 0xD) - 0x52250EC), 0xD) - 0x52250EC);

uint v5 = (size - 1) / 20;

uint v6 = Utilities.rotl(0xCC9E2D51 * size + 0x1B873593 * Utilities.rotl(0xCC9E2D51 * BitConverter.ToUInt32(data, (int)(size - 0x14)), 0xF), 0xD) + 0x71;

int offset = 8;
for (uint i = v5; i > 0; i--) {
uint v8 = BitConverter.ToUInt32(data, offset + 4);
uint v9 = BitConverter.ToUInt32(data, offset - 8);
uint v10 = BitConverter.ToUInt32(data, offset);
uint v11 = BitConverter.ToUInt32(data, offset + 8);
uint v12 = BitConverter.ToUInt32(data, offset - 4);
offset += 20;
uint v13 = Utilities.rotl((v9 + v3) ^ 0x1B873593 * Utilities.rotl(0xCC9E2D51 * v8, 0xF), 0xD);
v3 = v13 - 0x19AB949C + v11 + 4 * v13;
uint v14 = Utilities.rotl((v12 + v4) ^ 0x1B873593 * Utilities.rotl(0xCC9E2D51 * v10, 0xF), 0xD);
uint v15 = v14 - 0x19AB949C + v9 + 4 * v14;
uint v16 = Utilities.rotl((v10 + v6) ^ 0x1B873593 * Utilities.rotl(0x100193A1 * v11 - 0x3361D2AF * v12, 0xF), 0xD);
v6 = v15 + v16 + v8 + 4 * (v16 - 0x66AE527);
v4 = v6 + v15;
}

uint cksm = 0xCC9E2D51 * Utilities.rotl(5 * Utilities.rotl(0xCC9E2D51 * (Utilities.rotl(0xCC9E2D51 * Utilities.rotr(v6, 0xB), 0xF) + Utilities.rotl(5 * (Utilities.rotl(v3 - 0x3361D2AF * Utilities.rotl(0xCC9E2D51 * Utilities.rotr(v4, 0xB), 0xF), 0xD) - 0x52250EC), 0xF)), 0xD) - 0x19AB949C, 0xF);
byte[] cksmBytes = BitConverter.GetBytes(cksm);
Array.Reverse(cksmBytes);
return cksmBytes;
} else if (size > 0xC)
return null;
else if (size > 4)
return null;
else
return null;
}
}
}
4 changes: 2 additions & 2 deletions Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.3.0.3")]
[assembly: AssemblyFileVersion("1.3.0.3")]
[assembly: AssemblyVersion("1.3.0.4")]
[assembly: AssemblyFileVersion("1.3.0.4")]
6 changes: 1 addition & 5 deletions Utilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,9 @@ namespace DOOMSaveManager
{
public static class Utilities
{
public static uint rotl(uint n, int d) => (n << d) | (n >> (32 - d));

public static uint rotr(uint n, int d) => (n >> d) | (n << (32 - d));

public static string GetSteamPath() {
using (var reg = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Wow6432Node\Valve\Steam")) {
return (string)reg.GetValue("InstallPath", null);
return (string)reg.GetValue("InstallPath", "");
}
}

Expand Down

0 comments on commit c071bec

Please sign in to comment.