private static List <(byte[], byte[])> GeneratePlainEncryptedPairs(byte[] imageBytes) { var result = new List <(byte[], byte[])>(); var prefixWithEncryptedPixels = imageBytes.Skip(SubstitutionPermutationNetwork.GenerateRandomIV().Length + 0x38 - SubstitutionPermutationNetwork.BlockSizeBytes).ToList(); for (int i = SubstitutionPermutationNetwork.BlockSizeBytes; i < prefixWithEncryptedPixels.Count - SubstitutionPermutationNetwork.BlockSizeBytes; i += SubstitutionPermutationNetwork.BlockSizeBytes) { var prevC = prefixWithEncryptedPixels.Skip(i - SubstitutionPermutationNetwork.BlockSizeBytes).Take(SubstitutionPermutationNetwork.BlockSizeBytes).ToArray(); var c = prefixWithEncryptedPixels.Skip(i).Take(SubstitutionPermutationNetwork.BlockSizeBytes).ToArray(); var expectedP = new byte[] { 0, 0xFF, 0, 0, 0, 0xFF, 0, 0 }; var input = SubstitutionPermutationNetwork.XorBlock(prevC, expectedP); result.Add((input, c)); } return(result); }
static void Main(string[] args) { // ProofOfConecpt.Do(); // return; if (args.Length < 1) { Console.WriteLine("Usage: sploit.exe <fileToDecrypt> [expectedKey]"); Environment.Exit(1); } var expectedKey = args.Length >= 2 ? File.ReadAllBytes(args[1]) : new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; byte[] imageBytes; try { imageBytes = File.ReadAllBytes(args[0]); } catch (Exception e) { Console.WriteLine($"Can't read data from file {args[0]}", e); Environment.Exit(1); return; } var spn = new SubstitutionPermutationNetwork(SubstitutionPermutationNetwork.GenerateRandomKey()); var pairs = GeneratePlainEncryptedPairs(imageBytes); var plains = pairs.Select(tuple => tuple.Item1).ToArray(); var encs = pairs.Select(tuple => tuple.Item2).ToArray(); var linearCryptoanalysis = new LinearCryptoanalysis(spn); var bestLayerApproximations = linearCryptoanalysis.ChooseBestPathsStartingFromSingleSBoxInRound0(Exploit.maxSBoxesInLastRound, Exploit.maxSBoxesInRound, Exploit.thresholdBias).ToList(); Console.WriteLine($"Total approximations: {bestLayerApproximations.Count}"); var solutions = new List <Solution>(); foreach (var approximationsGroup in bestLayerApproximations .Where(layer => layer.round0sboxNum % 8 == 3 || (layer.round0sboxNum % 8 == 4 && ((layer.round0x & 0x01) == 0))) .GroupBy(layer => layer.ActivatedSboxesNums.Aggregate("", (s, num) => s + num)) .OrderBy(group => group.Key)) { foreach (var approximation in approximationsGroup.Distinct().OrderByDescending(layer => layer.inputProbability.Bias()).Take(6)) { solutions.AddRange(Exploit.HackApproximation(plains, encs, approximation, expectedKey)); } } var solutionsDict = Exploit.OrderSolutions(solutions, expectedKey); var imageLength = imageBytes.Length - SubstitutionPermutationNetwork.GenerateRandomIV().Length; if (imageLength >= 65536) { throw new Exception("Unexpected image ciphertext length"); } Console.WriteLine("\nBruting left bits.."); var plaintextPrefixFrom4 = new byte[] { 0, 0, 0, 0, 0, 0, 0x36, 0, 0, 0 }; var hackedKey = GetFinalSolution(solutionsDict, imageBytes.Take(24).ToArray(), plaintextPrefixFrom4); if (hackedKey != null) { Console.WriteLine($"\nHACKED KEY: {hackedKey.ToHexUpperCase()}"); } else { Console.WriteLine("BAD LUCK. Key not hacked"); } }
public static int ProcessPut(string host, string id, string flag) { try { var tcpClient = ConnectToService(host, PUT_PORT); using (var stream = tcpClient.GetStream()) { var xA = DH.GenerateRandomXA(DH_x_bitsCount); var yA = DH.CalculateYA(xA); stream.WriteBigEndian(yA); var yB = stream.ReadBigIntBigEndian(NetworkStreamExtensions.DH_y_bytesCount); var keyMaterial = DH.DeriveKey(yB, xA).ToByteArray(isBigEndian: true, isUnsigned: true); var masterKey = SubstitutionPermutationNetwork.CalcMasterKey(keyMaterial); var flagPicture = FlagsPainter.DrawFlag(flag); var spn = new SubstitutionPermutationNetwork(masterKey); var encryptedData = spn.EncryptWithPadding(flagPicture, SubstitutionPermutationNetwork.GenerateRandomIV()); stream.WriteLengthFieldAware(encryptedData); var imageId = stream.ReadIntBigEndian(); Console.Error.WriteLine($"Got image id {imageId}"); string imageHash; try { imageHash = CalcImageBytesHash(flagPicture); } catch (Exception e) { throw new ServiceException(ExitCode.CHECKER_ERROR, "Failed to calc hash of generated image", innerException: e); } var state = new State { FileId = imageId, MasterKeyHex = Convert.ToBase64String(masterKey), SourceImageHash = imageHash }; var lastImageId = FindLastId(host); SaveLastFileId(host, imageId); if (lastImageId != null) { if (Math.Abs(lastImageId.Value - imageId) > MaxConsecutiveFileIdsDiff) { throw new ServiceException(ExitCode.MUMBLE, $"LastImageId {lastImageId}, got new imageId {imageId}, difference is more than threshold {MaxConsecutiveFileIdsDiff}. Possibly service was 'patched' to make ids non-predictable. It's not fairplay, so punishing service's SLA", "Unexpected image id"); } } Console.WriteLine(state.ToJsonString().ToBase64String()); return((int)ExitCode.OK); } } catch (ServiceException) { throw; } catch (Exception e) { throw new ServiceException(ExitCode.DOWN, string.Format("General failure"), innerException: e); } }