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); }
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); }