private bool VerifyAllMatchedKeys(CryptoPatchContainer patches)
        {
            var samplePatch    = CryptoPatches.Find(p => !p.Inlined);
            var inlinedPatches = CryptoPatches.Where(p => p.Inlined);

            foreach (var inlinedPatch in inlinedPatches)
            {
                if (inlinedPatch.Keys[0].Key != samplePatch.Keys[0].Key)
                {
                    return(false);
                }

                if (inlinedPatch.Keys[2].Key != samplePatch.Keys[2].Key)
                {
                    return(false);
                }
            }

            var regularPatches = CryptoPatches.Where(p => !p.Inlined);

            foreach (var patch in regularPatches)
            {
                for (int i = 0; i < CryptoPatch.KEYS_COUNT; i++)
                {
                    if (patch.Keys[i].Key != samplePatch.Keys[i].Key)
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
Example #2
0
        private bool VerifyAllMatchedKeys(CryptoPatchContainer patches)
        {
            var samplePatch    = CryptoPatches.Find(p => !p.Inlined);
            var inlinedPatches = CryptoPatches.Where(p => p.Inlined);

            foreach (var inlinedPatch in inlinedPatches)
            {
                if (inlinedPatch.Keys[0].Key != samplePatch.Keys[0].Key)
                {
                    var keyVA = Calculator.OffsetToVA((ulong)inlinedPatch.Keys[0].Offset);
                    Log.Error($"Unmatched results. Inlined patch key1 (0x{keyVA:X8}) not equals to sample patch key1.");
                    return(false);
                }

                if (inlinedPatch.Keys[2].Key != samplePatch.Keys[2].Key)
                {
                    var keyVA = Calculator.OffsetToVA((ulong)inlinedPatch.Keys[2].Offset);
                    Log.Error($"Unmatched results. Inlined patch key3 (0x{keyVA:X8}) not equals to sample patch key3.");
                    return(false);
                }
            }

            var regularPatches = CryptoPatches.Where(p => !p.Inlined);

            foreach (var patch in regularPatches)
            {
                for (int i = 0; i < CryptoPatch.KEYS_COUNT; i++)
                {
                    if (patch.Keys[i].Key != samplePatch.Keys[i].Key)
                    {
                        var keyVA = Calculator.OffsetToVA((ulong)patch.Keys[i].Offset);
                        Log.Error($"Unmatched results. Regular patch key (0x{keyVA:X8}) not equals to sample patch key.");
                        return(false);
                    }
                }
            }

            return(true);
        }
        private bool InitKeysOffsets()
        {
            CryptoPatches.Clear();

            // "N3TableBase - Can't open file(read) File Handle..."
            var  pattern = Pattern.Transform("4E 33 54 61 62 6C 65 42 61 73 65 20 2D 20 43"); // "N3TableBase - C"
            long offsetLogWrite;

            if (!Pattern.Find(_data, pattern, out offsetLogWrite))
            {
                Console.WriteLine("[TargetPE::InitKeysOffsets]: Unable to find offset.");
                return(false);
            }

            // Generate pattern for finding all references to that string
            string logWriteVA         = Calculator.OffsetToVA((ulong)offsetLogWrite).ToString("X8");
            string logWriteGenPattern = "68"; // push

            for (int i = logWriteVA.Length - 1; i >= 0; --i)
            {
                logWriteGenPattern += i % 2 == 0 ? " " + logWriteVA.Substring(i, 2) : "";
            }
            logWriteGenPattern += " E8"; // call

            Console.WriteLine($"[TargetPE::InitKeysOffsets]: Generated pattern result: {logWriteGenPattern}");
            var         patternStrRefRegion = Pattern.Transform(logWriteGenPattern);
            List <long> regionStrRefOffsets;

            if (!Pattern.FindAll(_data, patternStrRefRegion, out regionStrRefOffsets))
            {
                Console.WriteLine("[TargetPE::InitKeysOffsets]: No offsets were found.");
                return(false);
            }

            Console.WriteLine($"[TargetPE::InitKeysOffsets]: Found {regionStrRefOffsets.Count} region offsets.");

            var patDecryptRegions = new Pattern.Byte[][] {
                // push ?? <- DWORD as short
                // push ?? <- DWORD as short
                // push ?? <- DWORD as short
                Pattern.Transform("68 ?? ?? 00 00 68 ?? ?? 00 00 68 ?? ?? 00 00 ?? ?? E8"),

                //Pattern.Transform("FF ?? ?? ?? ?? ?? 8B ?? ?? ?? ?? ?? 55 FF"),
                //Pattern.Transform("FF ?? ?? ?? ?? ?? 8B ?? ?? ?? ?? ?? 56 FF"),
                //Pattern.Transform("FF ?? ?? ?? ?? ?? 8B ?? ?? ?? ?? ?? 57 FF"),

                // call ?? <- ReadFile
                // push ebp|esi|edi
                // call ?? <- CloseHandle
                // xor reg,reg
                Pattern.Transform("FF ?? ?? ?? ?? ?? 55 FF"),
                Pattern.Transform("FF ?? ?? ?? ?? ?? 56 FF"),
                Pattern.Transform("FF ?? ?? ?? ?? ?? 57 FF"),
            };

            const int ENCRYPT_REGION_MIN        = 50;
            const int ENCRYPT_REGION_MAX        = 700;
            const int ESTIMATED_DES_RANGE_BYTES = 280;

            bool detectedDesEncryption = false;

            foreach (long regionStrRefOffset in regionStrRefOffsets)
            {
                long decryptRegionOffset = -1;
                bool isInlinedFunction   = false;
                for (int i = 0; i < patDecryptRegions.Length; i++)
                {
                    if (!Pattern.Find(_data, patDecryptRegions[i], out decryptRegionOffset,
                                      regionStrRefOffset + ENCRYPT_REGION_MIN, regionStrRefOffset + ENCRYPT_REGION_MAX))
                    {
                        continue;
                    }

                    // Estimate average distance by bytes, to know whether there is more code for DES encryption before XOR.
                    if (!detectedDesEncryption && (decryptRegionOffset - regionStrRefOffset) > ESTIMATED_DES_RANGE_BYTES)
                    {
                        detectedDesEncryption = true;
                    }

                    // First pattern: we know it's a function that got inlined by the compiler.
                    // +5 for ptr & +2 for xor reg,reg
                    isInlinedFunction = i != 0;
                    if (isInlinedFunction)
                    {
                        CanUpdateKey2        = false;
                        decryptRegionOffset += patDecryptRegions[i].Length + 5 + 2;
                    }

                    break;
                }

                if (decryptRegionOffset == -1)
                {
                    Console.WriteLine($"[TargetPE::InitKeysOffsets]: Unable to find decryption region offset.");
                    continue;
                }

                CryptoKey[] keys = new CryptoKey[CryptoPatch.KEYS_COUNT];

                MemoryStream ms = (MemoryStream)PE.GetStream();
                ms.Seek(decryptRegionOffset, SeekOrigin.Begin);

                if (isInlinedFunction)
                {
                    if (!InitInlinedKeys(keys, ms))
                    {
                        return(false);
                    }
                }
                else
                {
                    for (int i = CryptoPatch.KEYS_COUNT - 1; i >= 0; i--)
                    {
                        DWORD dword;
                        ms.Position++;
                        dword   = ms.ReadStructure <DWORD>();
                        keys[i] = new CryptoKey((ms.Position - 4), (ushort)dword.sValue1,
                                                (long)Calculator.OffsetToVA((ulong)(ms.Position - 4)));
                    }
                }
                long keyVA = (long)Calculator.OffsetToVA((ulong)decryptRegionOffset);
                var  patch = new CryptoPatch(decryptRegionOffset, keyVA, keys, isInlinedFunction);
                CryptoPatches.Add(patch);
            }

            // Update the container cryption type, so we know what we deal with
            CryptoPatches.CryptoType = detectedDesEncryption ? CryptoType.DES_XOR : CryptoType.XOR;

            if (CryptoPatches.Count != regionStrRefOffsets.Count)
            {
                return(false);
            }

            if (!VerifyAllMatchedKeys(CryptoPatches))
            {
                return(false);
            }

            return(true);
        }