public static void Generate(byte[] exeData) { var exeStr = new MemoryStream(exeData); PC_AES_KEY = HashSearch.SearchHash(exeStr, GTA5HashConstants.PC_AES_KEY_HASH, 0x20); Console.WriteLine("aes key found"); PC_NG_KEYS = HashSearch.SearchHashes(exeStr, GTA5HashConstants.PC_NG_KEY_HASHES, 0x110); Console.WriteLine("ng keys found"); var tabs = HashSearch.SearchHashes(exeStr, GTA5HashConstants.PC_NG_DECRYPT_TABLE_HASHES, 0x400); Console.WriteLine("ng decrypt tables found"); // 17 rounds PC_NG_DECRYPT_TABLES = new uint[17][][]; for (int i = 0; i < 17; i++) { // PC_NG_DECRYPT_TABLES[i] = new uint[16][]; for (int j = 0; j < 16; j++) { var buf = tabs[j + 16 * i]; PC_NG_DECRYPT_TABLES[i][j] = new uint[256]; Buffer.BlockCopy(buf, 0, PC_NG_DECRYPT_TABLES[i][j], 0, 1024); } } PC_LUT = HashSearch.SearchHash(exeStr, GTA5HashConstants.PC_LUT_HASH, 0x100); Console.WriteLine("ng hash LUTs found"); PC_NG_ENCRYPT_TABLES = new uint[17][][]; for (int i = 0; i < 17; i++) { PC_NG_ENCRYPT_TABLES[i] = new uint[16][]; for (int j = 0; j < 16; j++) { PC_NG_ENCRYPT_TABLES[i][j] = new uint[256]; for (int k = 0; k < 256; k++) { PC_NG_ENCRYPT_TABLES[i][j][k] = 0; } } } PC_NG_ENCRYPT_LUTs = new GTA5NGLUT[17][]; for (int i = 0; i < 17; i++) { PC_NG_ENCRYPT_LUTs[i] = new GTA5NGLUT[16]; for (int j = 0; j < 16; j++) PC_NG_ENCRYPT_LUTs[i][j] = new GTA5NGLUT(); } PC_NG_ENCRYPT_TABLES[0] = RandomGauss.Solve(PC_NG_DECRYPT_TABLES[0]); Console.WriteLine("ng encrypt table 1 of 17 calculated"); PC_NG_ENCRYPT_TABLES[1] = RandomGauss.Solve(PC_NG_DECRYPT_TABLES[1]); Console.WriteLine("ng encrypt table 2 of 17 calculated"); for (int k = 2; k <= 15; k++) { PC_NG_ENCRYPT_LUTs[k] = LookUpTableGenerator.BuildLUTs2(PC_NG_DECRYPT_TABLES[k]); Console.WriteLine("ng encrypt table " + (k + 1).ToString() + " of 17 calculated"); } PC_NG_ENCRYPT_TABLES[16] = RandomGauss.Solve(PC_NG_DECRYPT_TABLES[16]); Console.WriteLine("ng encrypt table 17 of 17 calculated"); }
public static GTA5NGLUT[][] ReadNgLuts(string fileName) { var fileStream = new FileStream(fileName, FileMode.Open); var dataReader = new DataReader(fileStream); var array = new GTA5NGLUT[17][]; for (var i = 0; i < 17; i++) { array[i] = new GTA5NGLUT[16]; for (var j = 0; j < 16; j++) { array[i][j] = new GTA5NGLUT(); array[i][j].LUT0 = new byte[256][]; for (var k = 0; k < 256; k++) { array[i][j].LUT0[k] = dataReader.ReadBytes(256); } array[i][j].LUT1 = new byte[256][]; for (var l = 0; l < 256; l++) { array[i][j].LUT1[l] = dataReader.ReadBytes(256); } array[i][j].Indices = dataReader.ReadBytes(65536); } } fileStream.Close(); return(array); }
public static void WriteLuts(string fileName, GTA5NGLUT[][] lutData) { FileStream fileStream = new FileStream(fileName, FileMode.Create); DataWriter dataWriter = new DataWriter(fileStream, Endianess.LittleEndian); for (int i = 0; i < 17; i++) { for (int j = 0; j < 16; j++) { GTA5NGLUT gta5NGLUT = lutData[i][j]; for (int k = 0; k < 256; k++) { for (int l = 0; l < 256; l++) { dataWriter.Write(gta5NGLUT.LUT0[k][l]); } } for (int m = 0; m < 256; m++) { for (int n = 0; n < 256; n++) { dataWriter.Write(gta5NGLUT.LUT1[m][n]); } } for (int num = 0; num < 65536; num++) { dataWriter.Write(gta5NGLUT.Indices[num]); } } } fileStream.Close(); }
public static GTA5NGLUT[][] ReadNgLuts(byte[] data) { var ms = new MemoryStream(data); var rd = new DataReader(ms); GTA5NGLUT[][] array = new GTA5NGLUT[17][]; for (int i = 0; i < 17; i++) { array[i] = new GTA5NGLUT[16]; for (int j = 0; j < 16; j++) { array[i][j] = new GTA5NGLUT(); array[i][j].LUT0 = new byte[256][]; for (int k = 0; k < 256; k++) { array[i][j].LUT0[k] = rd.ReadBytes(256); } array[i][j].LUT1 = new byte[256][]; for (int l = 0; l < 256; l++) { array[i][j].LUT1[l] = rd.ReadBytes(256); } array[i][j].Indices = rd.ReadBytes(65536); } } ms.Close(); return(array); }
public static GTA5NGLUT[][] ReadNgLuts(string fileName) { GTA5NGLUT[][] result; var fs = new FileStream(fileName, FileMode.Open); var rd = new DataReader(fs); // 17 rounds... result = new GTA5NGLUT[17][]; for (int i = 0; i < 17; i++) { // 16 bytes... result[i] = new GTA5NGLUT[16]; for (int j = 0; j < 16; j++) { result[i][j] = new GTA5NGLUT(); // first compression step (2^32 -> 2^24) result[i][j].LUT0 = new byte[256][]; for (int k = 0; k < 256; k++) { //result[i][j].LUT0[k] = new byte[256]; //for (int l = 0; l < 256; l++) // result[i][j].LUT0[k][l] = rd.ReadByte(); result[i][j].LUT0[k] = rd.ReadBytes(256); } // second compression step (2^24 -> 2^16) result[i][j].LUT1 = new byte[256][]; for (int k = 0; k < 256; k++) { //result[i][j].LUT1[k] = new byte[256]; //for (int l = 0; l < 256; l++) // result[i][j].LUT1[k][l] = rd.ReadByte(); result[i][j].LUT1[k] = rd.ReadBytes(256); } // indices //result[i][j].Indices = new byte[65536]; //for (int k = 0; k < 65536; k++) // result[i][j].Indices[k] = rd.ReadByte(); result[i][j].Indices = rd.ReadBytes(65536); } } fs.Dispose(); return(result); }
public static void WriteLuts(string fileName, GTA5NGLUT[][] lutData) { var fs = new FileStream(fileName, FileMode.Create); var wr = new DataWriter(fs); // 17 rounds... for (int i = 0; i < 17; i++) { // 16 bytes... for (int j = 0; j < 16; j++) { GTA5NGLUT lut = lutData[i][j]; // first compression step (2^32 -> 2^24) for (int k = 0; k < 256; k++) { for (int l = 0; l < 256; l++) { wr.Write(lut.LUT0[k][l]); } } // second compression step (2^24 -> 2^16) for (int k = 0; k < 256; k++) { for (int l = 0; l < 256; l++) { wr.Write(lut.LUT1[k][l]); } } // indices for (int k = 0; k < 65536; k++) { wr.Write(lut.Indices[k]); } } } fs.Dispose(); }
public static byte[] EncryptRoundB_LUT(byte[] dataOld, uint[] key, GTA5NGLUT[] lut) { var data = (byte[])dataOld.Clone(); // apply xor to data first... var xorbuf = new byte[16]; Buffer.BlockCopy(key, 0, xorbuf, 0, 16); for (int y = 0; y < 16; y++) { data[y] ^= xorbuf[y]; } return new byte[] { lut[0].LookUp(BitConverter.ToUInt32( new byte[] { data[0], data[1], data[2], data[3] }, 0)), lut[1].LookUp(BitConverter.ToUInt32( new byte[] { data[4], data[5], data[6], data[7] }, 0)), lut[2].LookUp(BitConverter.ToUInt32( new byte[] { data[8], data[9], data[10], data[11] }, 0)), lut[3].LookUp(BitConverter.ToUInt32( new byte[] { data[12], data[13], data[14], data[15] }, 0)), lut[4].LookUp(BitConverter.ToUInt32( new byte[] { data[4], data[5], data[6], data[7] }, 0)), lut[5].LookUp(BitConverter.ToUInt32( new byte[] { data[8], data[9], data[10], data[11] }, 0)), lut[6].LookUp(BitConverter.ToUInt32( new byte[] { data[12], data[13], data[14], data[15] }, 0)), lut[7].LookUp(BitConverter.ToUInt32( new byte[] { data[0], data[1], data[2], data[3] }, 0)), lut[8].LookUp(BitConverter.ToUInt32( new byte[] { data[8], data[9], data[10], data[11] }, 0)), lut[9].LookUp(BitConverter.ToUInt32( new byte[] { data[12], data[13], data[14], data[15] }, 0)), lut[10].LookUp(BitConverter.ToUInt32( new byte[] { data[0], data[1], data[2], data[3] }, 0)), lut[11].LookUp(BitConverter.ToUInt32( new byte[] { data[4], data[5], data[6], data[7] }, 0)), lut[12].LookUp(BitConverter.ToUInt32( new byte[] { data[12], data[13], data[14], data[15] }, 0)), lut[13].LookUp(BitConverter.ToUInt32( new byte[] { data[0], data[1], data[2], data[3] }, 0)), lut[14].LookUp(BitConverter.ToUInt32( new byte[] { data[4], data[5], data[6], data[7] }, 0)), lut[15].LookUp(BitConverter.ToUInt32( new byte[] { data[8], data[9], data[10], data[11] }, 0))}; }
public static GTA5NGLUT[] BuildLUTs2(uint[][] tables) { var temp = new byte[16][]; for (int i = 0; i < 16; i++) temp[i] = new byte[65536]; var result = new GTA5NGLUT[16]; for (int i = 0; i < 16; i++) { result[i] = new GTA5NGLUT(); //result[i].Tables = new byte[256][]; //result[i].LUT = new byte[16777216]; } var tempLUTS = new byte[16][]; for (int i = 0; i < 16; i++) tempLUTS[i] = new byte[16777216]; var t0 = tables[0]; var t1 = tables[1]; var t2 = tables[2]; var t3 = tables[3]; var t4 = tables[4]; var t5 = tables[5]; var t6 = tables[6]; var t7 = tables[7]; var t8 = tables[8]; var t9 = tables[9]; var t10 = tables[10]; var t11 = tables[11]; var t12 = tables[12]; var t13 = tables[13]; var t14 = tables[14]; var t15 = tables[15]; Parallel.For(0, 0x100, (long k1) => { for (long k2 = 0; k2 < 0x1000000; k2++) { long i = k1 * 0x1000000 + k2; byte b0 = (byte)((i >> 0) & 0xFF); byte b1 = (byte)((i >> 8) & 0xFF); byte b2 = (byte)((i >> 16) & 0xFF); byte b3 = (byte)((i >> 24) & 0xFF); var x1 = t0[b0] ^ t7[b1] ^ t10[b2] ^ t13[b3]; var x2 = t1[b0] ^ t4[b1] ^ t11[b2] ^ t14[b3]; var x3 = t2[b0] ^ t5[b1] ^ t8[b2] ^ t15[b3]; var x4 = t3[b0] ^ t6[b1] ^ t9[b2] ^ t12[b3]; // the first LUT-compression step is built-it // because it would take 4GB ram per data byte (and there are 16) if (x1 < 65536) { temp[0][x1] = b0; temp[7][x1] = b1; temp[10][x1] = b2; temp[13][x1] = b3; } if (x2 < 65536) { temp[1][x2] = b0; temp[4][x2] = b1; temp[11][x2] = b2; temp[14][x2] = b3; } if (x3 < 65536) { temp[2][x3] = b0; temp[5][x3] = b1; temp[8][x3] = b2; temp[15][x3] = b3; } if (x4 < 65536) { temp[3][x4] = b0; temp[6][x4] = b1; temp[9][x4] = b2; temp[12][x4] = b3; } if ((x1 & 0x000000FF) == 0) { tempLUTS[0][x1 >> 8] = b0; tempLUTS[7][x1 >> 8] = b1; tempLUTS[10][x1 >> 8] = b2; tempLUTS[13][x1 >> 8] = b3; } if ((x2 & 0x000000FF) == 0) { tempLUTS[1][x2 >> 8] = b0; tempLUTS[4][x2 >> 8] = b1; tempLUTS[11][x2 >> 8] = b2; tempLUTS[14][x2 >> 8] = b3; } if ((x3 & 0x000000FF) == 0) { tempLUTS[2][x3 >> 8] = b0; tempLUTS[5][x3 >> 8] = b1; tempLUTS[8][x3 >> 8] = b2; tempLUTS[15][x3 >> 8] = b3; } if ((x4 & 0x000000FF) == 0) { tempLUTS[3][x4 >> 8] = b0; tempLUTS[6][x4 >> 8] = b1; tempLUTS[9][x4 >> 8] = b2; tempLUTS[12][x4 >> 8] = b3; } } }); for (int i = 0; i < 16; i++) { result[i].LUT0 = new byte[256][]; for (int blockIdx = 0; blockIdx < 256; blockIdx++) { var xl = new byte[256]; for (int k = 0; k < 256; k++) { xl[k] = temp[i][256 * blockIdx + k]; } result[i].LUT0[xl[0]] = xl; } } // compress tables... // length from 2^24 -> 2^16 for (int i = 0; i < 16; i++) { GTA5NGLUT lut = result[i]; lut.LUT1 = new byte[256][]; lut.Indices = new byte[65536]; for (int blockIdx = 0; blockIdx < 256; blockIdx++) { var xl = new byte[256]; for (int k = 0; k < 256; k++) { xl[k] = tempLUTS[i][256 * blockIdx + k]; } lut.LUT1[xl[0]] = xl; } for (int blockIdx = 0; blockIdx < 65536; blockIdx++) { lut.Indices[blockIdx] = tempLUTS[i][256 * blockIdx]; } } return result; }
public static void WriteLuts(string fileName, GTA5NGLUT[][] lutData) { var fs = new FileStream(fileName, FileMode.Create); var wr = new DataWriter(fs); // 17 rounds... for (int i = 0; i < 17; i++) { // 16 bytes... for (int j = 0; j < 16; j++) { GTA5NGLUT lut = lutData[i][j]; // first compression step (2^32 -> 2^24) for (int k = 0; k < 256; k++) for (int l = 0; l < 256; l++) wr.Write(lut.LUT0[k][l]); // second compression step (2^24 -> 2^16) for (int k = 0; k < 256; k++) for (int l = 0; l < 256; l++) wr.Write(lut.LUT1[k][l]); // indices for (int k = 0; k < 65536; k++) wr.Write(lut.Indices[k]); } } fs.Close(); }
public static GTA5NGLUT[][] ReadNgLuts(string fileName) { GTA5NGLUT[][] result; var fs = new FileStream(fileName, FileMode.Open); var rd = new DataReader(fs); // 17 rounds... result = new GTA5NGLUT[17][]; for (int i = 0; i < 17; i++) { // 16 bytes... result[i] = new GTA5NGLUT[16]; for (int j = 0; j < 16; j++) { result[i][j] = new GTA5NGLUT(); // first compression step (2^32 -> 2^24) result[i][j].LUT0 = new byte[256][]; for (int k = 0; k < 256; k++) { //result[i][j].LUT0[k] = new byte[256]; //for (int l = 0; l < 256; l++) // result[i][j].LUT0[k][l] = rd.ReadByte(); result[i][j].LUT0[k] = rd.ReadBytes(256); } // second compression step (2^24 -> 2^16) result[i][j].LUT1 = new byte[256][]; for (int k = 0; k < 256; k++) { //result[i][j].LUT1[k] = new byte[256]; //for (int l = 0; l < 256; l++) // result[i][j].LUT1[k][l] = rd.ReadByte(); result[i][j].LUT1[k] = rd.ReadBytes(256); } // indices //result[i][j].Indices = new byte[65536]; //for (int k = 0; k < 65536; k++) // result[i][j].Indices[k] = rd.ReadByte(); result[i][j].Indices = rd.ReadBytes(65536); } } fs.Close(); return result; }