static void DecryptApCode(DataStream stream, Configuration config) { uint[,] encryptInfo = new uint[, ] { // seed offset length { 0x02175b00, 0x0215d0d8, 0x0215e44c }, { 0x0216F306, 0x0215D87C, 0x0215E388 }, { 0x0216D1F2, 0x0215C2F0, 0x0215E3DC }, { 0x02175760, 0x0215CDA0, 0x0215E44C }, { 0x0216F5B6, 0x0215DAB4, 0x0215E5F0 }, { 0x0216D452, 0x0215C528, 0x0215E3DC }, }; for (int i = 0; i < encryptInfo.GetLength(0); i++) { uint seed = encryptInfo[i, 0] - config.ConstantOffset - config.AddressOffset; uint offset = encryptInfo[i, 1] - config.AddressOffset; uint length = encryptInfo[i, 2] - config.ConstantOffset - config.AddressOffset; offset -= config.OverlayRamAddress; using (var input = new DataStream(stream, offset, length)) using (var output = new DataStream(stream, offset, length)) { Console.WriteLine($"* RC4N {offset:X4}h - {length:X4}h"); Rc4N.Decrypt(seed, input, output); } } }
public static void Decrypt(uint seed, DataStream input, DataStream output) { // seed seems to be always the same but the input length is variable byte[] key = GenerateKey(seed, (uint)input.Length); var rc4n = new Rc4N(key); rc4n.Run(input, output); }