From 0eaa1466fbe63560b401cd65bf1980bb16e24ca6 Mon Sep 17 00:00:00 2001 From: de4dot Date: Sun, 29 Jul 2012 20:02:12 +0200 Subject: [PATCH] Move common code to a base class --- de4dot.code/de4dot.code.csproj | 1 + .../Confuser/JitMethodsDecrypter.cs | 318 +--------------- .../Confuser/MethodsDecrypterBase.cs | 346 ++++++++++++++++++ 3 files changed, 354 insertions(+), 311 deletions(-) create mode 100644 de4dot.code/deobfuscators/Confuser/MethodsDecrypterBase.cs diff --git a/de4dot.code/de4dot.code.csproj b/de4dot.code/de4dot.code.csproj index 4026bf13..f03252cd 100644 --- a/de4dot.code/de4dot.code.csproj +++ b/de4dot.code/de4dot.code.csproj @@ -75,6 +75,7 @@ + diff --git a/de4dot.code/deobfuscators/Confuser/JitMethodsDecrypter.cs b/de4dot.code/deobfuscators/Confuser/JitMethodsDecrypter.cs index 7f81722b..e6b01620 100644 --- a/de4dot.code/deobfuscators/Confuser/JitMethodsDecrypter.cs +++ b/de4dot.code/deobfuscators/Confuser/JitMethodsDecrypter.cs @@ -20,7 +20,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Security.Cryptography; using System.Text; using Mono.Cecil; using Mono.Cecil.Cil; @@ -30,17 +29,10 @@ using de4dot.blocks; using de4dot.PE; namespace de4dot.code.deobfuscators.Confuser { - class JitMethodsDecrypter : IStringDecrypter { - ModuleDefinition module; - ISimpleDeobfuscator simpleDeobfuscator; - MethodDefinition initMethod; + class JitMethodsDecrypter : MethodsDecrypterBase, IStringDecrypter { MethodDefinition compileMethod; MethodDefinition hookConstructStr; - MethodDefinition decryptMethod; - ulong lkey0; - uint key0, key1, key2, key3, key4, key5, key6; MethodDataIndexes methodDataIndexes; - byte[] methodsData; struct MethodDataIndexes { public int codeSize; @@ -50,57 +42,15 @@ namespace de4dot.code.deobfuscators.Confuser { public int options; } - public MethodDefinition InitMethod { - get { return initMethod; } + public JitMethodsDecrypter(ModuleDefinition module, ISimpleDeobfuscator simpleDeobfuscator) + : base(module, simpleDeobfuscator) { } - public TypeDefinition Type { - get { return initMethod != null ? initMethod.DeclaringType : null; } + public JitMethodsDecrypter(ModuleDefinition module, JitMethodsDecrypter other) + : base(module, other) { } - public bool Detected { - get { return initMethod != null; } - } - - public JitMethodsDecrypter(ModuleDefinition module, ISimpleDeobfuscator simpleDeobfuscator) { - this.module = module; - this.simpleDeobfuscator = simpleDeobfuscator; - } - - public JitMethodsDecrypter(ModuleDefinition module, JitMethodsDecrypter other) { - this.module = module; - this.initMethod = lookup(other.initMethod, "Could not find initMethod"); - } - - T lookup(T def, string errorMessage) where T : MemberReference { - return DeobUtils.lookup(module, def, errorMessage); - } - - public void find() { - find(DotNetUtils.getModuleTypeCctor(module)); - } - - bool find(MethodDefinition method) { - if (method == null || method.Body == null) - return false; - foreach (var instr in method.Body.Instructions) { - if (instr.OpCode.Code != Code.Call) - continue; - var calledMethod = instr.Operand as MethodDefinition; - if (calledMethod == null || calledMethod.Body == null) - continue; - if (!DotNetUtils.isMethod(calledMethod, "System.Void", "()")) - continue; - if (!checkType(calledMethod.DeclaringType)) - continue; - - initMethod = calledMethod; - return true; - } - return false; - } - - bool checkType(TypeDefinition type) { + protected override bool checkType(TypeDefinition type, MethodDefinition initMethod) { if (type == null) return false; if (type.NestedTypes.Count != 27) @@ -112,7 +62,7 @@ namespace de4dot.code.deobfuscators.Confuser { hookConstructStr = findHookConstructStr(type); if (hookConstructStr == null) return false; - decryptMethod = findDecrypt(type); + decryptMethod = findDecryptMethod(type); if (decryptMethod == null) return false; @@ -165,18 +115,6 @@ namespace de4dot.code.deobfuscators.Confuser { return null; } - static MethodDefinition findDecrypt(TypeDefinition type) { - foreach (var method in type.Methods) { - if (!method.IsStatic || method.Body == null) - continue; - if (!DotNetUtils.isMethod(method, "System.Byte[]", "(System.Byte[],System.Byte[],System.Byte[])")) - continue; - - return method; - } - return null; - } - public void initialize() { if (initMethod == null) return; @@ -212,134 +150,6 @@ namespace de4dot.code.deobfuscators.Confuser { return true; } - static bool findLKey0(MethodDefinition method, out ulong key) { - var instrs = method.Body.Instructions; - for (int index = 0; index < instrs.Count; index++) { - index = findCallvirtReadUInt64(instrs, index); - if (index < 0) - break; - if (index + 1 >= instrs.Count) - continue; - var ldci8 = instrs[index + 1]; - if (ldci8.OpCode.Code != Code.Ldc_I8) - continue; - - key = (ulong)(long)ldci8.Operand; - return true; - } - - key = 0; - return false; - } - - static bool findKey0(MethodDefinition method, out uint key) { - var instrs = method.Body.Instructions; - for (int i = 0; i + 5 < instrs.Count; i++) { - i = findCallvirtReadUInt32(instrs, i); - if (i < 0) - break; - - int index = i + 1; - var ldci4_1 = instrs[index++]; - if (!DotNetUtils.isLdcI4(ldci4_1)) - continue; - if (instrs[index++].OpCode.Code != Code.Xor) - continue; - if (!DotNetUtils.isStloc(instrs[index++])) - continue; - if (!DotNetUtils.isLdloc(instrs[index++])) - continue; - var ldci4_2 = instrs[index++]; - if (!DotNetUtils.isLdcI4(ldci4_2)) - continue; - if (DotNetUtils.getLdcI4Value(ldci4_1) != DotNetUtils.getLdcI4Value(ldci4_2)) - continue; - - key = (uint)DotNetUtils.getLdcI4Value(ldci4_1); - return true; - } - - key = 0; - return false; - } - - static bool findKey1(MethodDefinition method, out uint key) { - var instrs = method.Body.Instructions; - for (int index = 0; index < instrs.Count; index++) { - index = findCallvirtReadUInt32(instrs, index); - if (index < 0) - break; - if (index == 0) - continue; - int i = index - 1; - if (!checkCallvirtReadUInt32(instrs, ref i)) - continue; - if (!checkCallvirtReadUInt32(instrs, ref i)) - continue; - if (!checkCallvirtReadUInt32(instrs, ref i)) - continue; - if (!checkCallvirtReadUInt32(instrs, ref i)) - continue; - - if (i + 1 >= instrs.Count) - continue; - if (!DotNetUtils.isLdloc(instrs[i])) - continue; - var ldci4 = instrs[i + 1]; - if (!DotNetUtils.isLdcI4(ldci4)) - continue; - - key = (uint)DotNetUtils.getLdcI4Value(ldci4); - return true; - } - - key = 0; - return false; - } - - static bool findKey2Key3(MethodDefinition method, out uint key2, out uint key3) { - var instrs = method.Body.Instructions; - for (int i = 0; i < instrs.Count; i++) { - int index = i; - if (!findKey2OrKey3(instrs, ref index, out key2)) - continue; - if (!findKey2OrKey3(instrs, ref index, out key3)) - continue; - - return true; - } - - key2 = 0; - key3 = 0; - return false; - } - - static bool findKey2OrKey3(IList instrs, ref int index, out uint key) { - key = 0; - if (index + 6 >= instrs.Count) - return false; - int i = index; - if (!DotNetUtils.isLdloc(instrs[i++])) - return false; - if (!DotNetUtils.isLdloc(instrs[i++])) - return false; - if (!ConfuserUtils.isCallMethod(instrs[i++], Code.Callvirt, "System.Int32 System.IO.BinaryReader::ReadInt32()")) - return false; - var ldci4 = instrs[i++]; - if (!DotNetUtils.isLdcI4(ldci4)) - return false; - if (instrs[i++].OpCode.Code != Code.Xor) - return false; - if (!ConfuserUtils.isCallMethod(instrs[i++], Code.Callvirt, "System.Byte[] System.IO.BinaryReader::ReadBytes(System.Int32)")) - return false; - if (!DotNetUtils.isStloc(instrs[i++])) - return false; - - key = (uint)DotNetUtils.getLdcI4Value(ldci4); - index = i; - return true; - } - static bool findKey4(MethodDefinition method, out uint key) { var instrs = method.Body.Instructions; for (int index = 0; index < instrs.Count; index++) { @@ -387,55 +197,6 @@ namespace de4dot.code.deobfuscators.Confuser { return false; } - static bool findKey6(MethodDefinition method, out uint key) { - var instrs = method.Body.Instructions; - for (int i = 0; i + 4 < instrs.Count; i++) { - int index = i; - if (!DotNetUtils.isLdloc(instrs[index++])) - continue; - if (instrs[index++].OpCode.Code != Code.Sub) - continue; - if (instrs[index++].OpCode.Code != Code.Ldelem_U1) - continue; - var ldci4 = instrs[index++]; - if (!DotNetUtils.isLdcI4(ldci4)) - continue; - if (instrs[index++].OpCode.Code != Code.Xor) - continue; - if (instrs[index++].OpCode.Code != Code.Conv_U1) - continue; - - key = (uint)DotNetUtils.getLdcI4Value(ldci4); - return true; - } - - key = 0; - return false; - } - - static bool checkCallvirtReadUInt32(IList instrs, ref int index) { - if (index + 2 >= instrs.Count) - return false; - - if (!DotNetUtils.isLdloc(instrs[index])) - return false; - if (!ConfuserUtils.isCallMethod(instrs[index + 1], Code.Callvirt, "System.UInt32 System.IO.BinaryReader::ReadUInt32()")) - return false; - if (!DotNetUtils.isStloc(instrs[index + 2])) - return false; - - index += 3; - return true; - } - - static int findCallvirtReadUInt32(IList instrs, int index) { - return ConfuserUtils.findCallMethod(instrs, index, Code.Callvirt, "System.UInt32 System.IO.BinaryReader::ReadUInt32()"); - } - - static int findCallvirtReadUInt64(IList instrs, int index) { - return ConfuserUtils.findCallMethod(instrs, index, Code.Callvirt, "System.UInt64 System.IO.BinaryReader::ReadUInt64()"); - } - bool initializeMethodDataIndexes(MethodDefinition method) { var methodDataType = findFirstThreeIndexes(method, out methodDataIndexes.maxStack, out methodDataIndexes.ehs, out methodDataIndexes.options); if (methodDataType == null) @@ -573,71 +334,6 @@ namespace de4dot.code.deobfuscators.Confuser { return dumpedMethods != null; } - byte[] decryptMethodsData(PeImage peImage) { - uint mdRva = peImage.OptionalHeader.checkSum ^ (uint)key0; - if (peImage.rvaToOffset(mdRva) != peImage.Cor20Header.MetadataOffset) - throw new ApplicationException("Invalid metadata rva"); - var reader = peImage.Reader; - reader.BaseStream.Position = getEncryptedHeaderOffset(peImage.Sections); - ulong checkSum = reader.ReadUInt64() ^ lkey0; - reader.ReadInt32(); // strong name RVA - reader.ReadInt32(); // strong name len - var iv = reader.ReadBytes(reader.ReadInt32() ^ (int)key2); - var encrypted = reader.ReadBytes(reader.ReadInt32() ^ (int)key3); - var streamsBuffer = getStreamsBuffer(peImage); - if (checkSum != calcChecksum(streamsBuffer)) - throw new ApplicationException("Invalid checksum. File has been modified."); - var decrypted = decrypt(encrypted, iv, streamsBuffer); - if (BitConverter.ToInt16(decrypted, 0) != 0x6FD6) - throw new ApplicationException("Invalid magic"); - return decrypted; - } - - byte[] decrypt(byte[] encrypted, byte[] iv, byte[] streamsBuffer) { - var decrypted = DeobUtils.aesDecrypt(encrypted, DeobUtils.sha256Sum(streamsBuffer), iv); - var sha = SHA512.Create(); - var hash = sha.ComputeHash(streamsBuffer); - for (int i = 0; i < decrypted.Length; i += 64) { - int j; - for (j = 0; j < 64 && i + j < decrypted.Length; j++) - decrypted[i + j] ^= (byte)(hash[j] ^ key6); - hash = sha.ComputeHash(decrypted, i, j); - } - return decrypted; - } - - static ulong calcChecksum(byte[] data) { - var sum = DeobUtils.md5Sum(data); - return BitConverter.ToUInt64(sum, 0) ^ BitConverter.ToUInt64(sum, 8); - } - - static byte[] getStreamsBuffer(PeImage peImage) { - var memStream = new MemoryStream(); - var writer = new BinaryWriter(memStream); - var reader = peImage.Reader; - foreach (var mdStream in peImage.Cor20Header.metadata.Streams) { - reader.BaseStream.Position = mdStream.Offset; - writer.Write(reader.ReadBytes((int)mdStream.length)); - } - return memStream.ToArray(); - } - - uint getEncryptedHeaderOffset(IList sections) { - for (int i = sections.Count - 1; i >= 0; i--) { - var section = sections[i]; - if (getSectionNameHash(section) == (uint)key1) - return section.pointerToRawData; - } - throw new ApplicationException("Could not find encrypted section"); - } - - static uint getSectionNameHash(SectionHeader section) { - uint hash = 0; - foreach (var c in section.name) - hash += c; - return hash; - } - DumpedMethods decrypt(PeImage peImage, byte[] fileData) { var dumpedMethods = new DumpedMethods { StringDecrypter = this }; diff --git a/de4dot.code/deobfuscators/Confuser/MethodsDecrypterBase.cs b/de4dot.code/deobfuscators/Confuser/MethodsDecrypterBase.cs new file mode 100644 index 00000000..5e345669 --- /dev/null +++ b/de4dot.code/deobfuscators/Confuser/MethodsDecrypterBase.cs @@ -0,0 +1,346 @@ +/* + Copyright (C) 2011-2012 de4dot@gmail.com + + This file is part of de4dot. + + de4dot is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + de4dot is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with de4dot. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Security.Cryptography; +using Mono.Cecil; +using Mono.Cecil.Cil; +using de4dot.blocks; +using de4dot.PE; + +namespace de4dot.code.deobfuscators.Confuser { + abstract class MethodsDecrypterBase { + protected ModuleDefinition module; + protected ISimpleDeobfuscator simpleDeobfuscator; + protected MethodDefinition initMethod; + protected MethodDefinition decryptMethod; + protected ulong lkey0; + protected uint key0, key1, key2, key3, key4, key5, key6; + protected byte[] methodsData; + + public MethodDefinition InitMethod { + get { return initMethod; } + } + + public TypeDefinition Type { + get { return initMethod != null ? initMethod.DeclaringType : null; } + } + + public bool Detected { + get { return initMethod != null; } + } + + protected MethodsDecrypterBase(ModuleDefinition module, ISimpleDeobfuscator simpleDeobfuscator) { + this.module = module; + this.simpleDeobfuscator = simpleDeobfuscator; + } + + protected MethodsDecrypterBase(ModuleDefinition module, MethodsDecrypterBase other) { + this.module = module; + if (other != null) + this.initMethod = lookup(other.initMethod, "Could not find initMethod"); + } + + T lookup(T def, string errorMessage) where T : MemberReference { + return DeobUtils.lookup(module, def, errorMessage); + } + + public void find() { + find(DotNetUtils.getModuleTypeCctor(module)); + } + + bool find(MethodDefinition method) { + if (method == null || method.Body == null) + return false; + foreach (var instr in method.Body.Instructions) { + if (instr.OpCode.Code != Code.Call) + continue; + var calledMethod = instr.Operand as MethodDefinition; + if (calledMethod == null || calledMethod.Body == null) + continue; + if (!DotNetUtils.isMethod(calledMethod, "System.Void", "()")) + continue; + if (!checkType(calledMethod.DeclaringType, calledMethod)) + continue; + + initMethod = calledMethod; + return true; + } + return false; + } + + protected abstract bool checkType(TypeDefinition type, MethodDefinition initMethod); + + protected static MethodDefinition findDecryptMethod(TypeDefinition type) { + foreach (var method in type.Methods) { + if (!method.IsStatic || method.Body == null) + continue; + if (!DotNetUtils.isMethod(method, "System.Byte[]", "(System.Byte[],System.Byte[],System.Byte[])")) + continue; + + return method; + } + return null; + } + + protected static bool findLKey0(MethodDefinition method, out ulong key) { + var instrs = method.Body.Instructions; + for (int index = 0; index < instrs.Count; index++) { + index = findCallvirtReadUInt64(instrs, index); + if (index < 0) + break; + if (index + 1 >= instrs.Count) + continue; + var ldci8 = instrs[index + 1]; + if (ldci8.OpCode.Code != Code.Ldc_I8) + continue; + + key = (ulong)(long)ldci8.Operand; + return true; + } + + key = 0; + return false; + } + + protected static bool findKey0(MethodDefinition method, out uint key) { + var instrs = method.Body.Instructions; + for (int i = 0; i + 5 < instrs.Count; i++) { + i = findCallvirtReadUInt32(instrs, i); + if (i < 0) + break; + + int index = i + 1; + var ldci4_1 = instrs[index++]; + if (!DotNetUtils.isLdcI4(ldci4_1)) + continue; + if (instrs[index++].OpCode.Code != Code.Xor) + continue; + if (!DotNetUtils.isStloc(instrs[index++])) + continue; + if (!DotNetUtils.isLdloc(instrs[index++])) + continue; + var ldci4_2 = instrs[index++]; + if (!DotNetUtils.isLdcI4(ldci4_2)) + continue; + if (DotNetUtils.getLdcI4Value(ldci4_1) != DotNetUtils.getLdcI4Value(ldci4_2)) + continue; + + key = (uint)DotNetUtils.getLdcI4Value(ldci4_1); + return true; + } + + key = 0; + return false; + } + + protected static bool findKey1(MethodDefinition method, out uint key) { + var instrs = method.Body.Instructions; + for (int index = 0; index < instrs.Count; index++) { + index = findCallvirtReadUInt32(instrs, index); + if (index < 0) + break; + if (index == 0) + continue; + int i = index - 1; + if (!checkCallvirtReadUInt32(instrs, ref i)) + continue; + if (!checkCallvirtReadUInt32(instrs, ref i)) + continue; + if (!checkCallvirtReadUInt32(instrs, ref i)) + continue; + if (!checkCallvirtReadUInt32(instrs, ref i)) + continue; + + if (i + 1 >= instrs.Count) + continue; + if (!DotNetUtils.isLdloc(instrs[i])) + continue; + var ldci4 = instrs[i + 1]; + if (!DotNetUtils.isLdcI4(ldci4)) + continue; + + key = (uint)DotNetUtils.getLdcI4Value(ldci4); + return true; + } + + key = 0; + return false; + } + + static bool checkCallvirtReadUInt32(IList instrs, ref int index) { + if (index + 2 >= instrs.Count) + return false; + + if (!DotNetUtils.isLdloc(instrs[index])) + return false; + if (!ConfuserUtils.isCallMethod(instrs[index + 1], Code.Callvirt, "System.UInt32 System.IO.BinaryReader::ReadUInt32()")) + return false; + if (!DotNetUtils.isStloc(instrs[index + 2]) && instrs[index + 2].OpCode.Code != Code.Pop) + return false; + + index += 3; + return true; + } + + protected static bool findKey2Key3(MethodDefinition method, out uint key2, out uint key3) { + var instrs = method.Body.Instructions; + for (int i = 0; i < instrs.Count; i++) { + int index = i; + if (!findKey2OrKey3(instrs, ref index, out key2)) + continue; + if (!findKey2OrKey3(instrs, ref index, out key3)) + continue; + + return true; + } + + key2 = 0; + key3 = 0; + return false; + } + + static bool findKey2OrKey3(IList instrs, ref int index, out uint key) { + key = 0; + if (index + 6 >= instrs.Count) + return false; + int i = index; + if (!DotNetUtils.isLdloc(instrs[i++])) + return false; + if (!DotNetUtils.isLdloc(instrs[i++])) + return false; + if (!ConfuserUtils.isCallMethod(instrs[i++], Code.Callvirt, "System.Int32 System.IO.BinaryReader::ReadInt32()")) + return false; + var ldci4 = instrs[i++]; + if (!DotNetUtils.isLdcI4(ldci4)) + return false; + if (instrs[i++].OpCode.Code != Code.Xor) + return false; + if (!ConfuserUtils.isCallMethod(instrs[i++], Code.Callvirt, "System.Byte[] System.IO.BinaryReader::ReadBytes(System.Int32)")) + return false; + if (!DotNetUtils.isStloc(instrs[i++])) + return false; + + key = (uint)DotNetUtils.getLdcI4Value(ldci4); + index = i; + return true; + } + + protected static bool findKey6(MethodDefinition method, out uint key) { + var instrs = method.Body.Instructions; + for (int i = 0; i + 4 < instrs.Count; i++) { + int index = i; + if (!DotNetUtils.isLdloc(instrs[index++])) + continue; + if (instrs[index++].OpCode.Code != Code.Sub) + continue; + if (instrs[index++].OpCode.Code != Code.Ldelem_U1) + continue; + var ldci4 = instrs[index++]; + if (!DotNetUtils.isLdcI4(ldci4)) + continue; + if (instrs[index++].OpCode.Code != Code.Xor) + continue; + if (instrs[index++].OpCode.Code != Code.Conv_U1) + continue; + + key = (uint)DotNetUtils.getLdcI4Value(ldci4); + return true; + } + + key = 0; + return false; + } + + protected static int findCallvirtReadUInt32(IList instrs, int index) { + return ConfuserUtils.findCallMethod(instrs, index, Code.Callvirt, "System.UInt32 System.IO.BinaryReader::ReadUInt32()"); + } + + static int findCallvirtReadUInt64(IList instrs, int index) { + return ConfuserUtils.findCallMethod(instrs, index, Code.Callvirt, "System.UInt64 System.IO.BinaryReader::ReadUInt64()"); + } + + protected byte[] decryptMethodsData(PeImage peImage) { + uint mdRva = peImage.OptionalHeader.checkSum ^ (uint)key0; + if (peImage.rvaToOffset(mdRva) != peImage.Cor20Header.MetadataOffset) + throw new ApplicationException("Invalid metadata rva"); + var reader = peImage.Reader; + reader.BaseStream.Position = getEncryptedHeaderOffset(peImage.Sections); + ulong checkSum = reader.ReadUInt64() ^ lkey0; + reader.ReadInt32(); // strong name RVA + reader.ReadInt32(); // strong name len + var iv = reader.ReadBytes(reader.ReadInt32() ^ (int)key2); + var encrypted = reader.ReadBytes(reader.ReadInt32() ^ (int)key3); + var streamsBuffer = getStreamsBuffer(peImage); + if (checkSum != calcChecksum(streamsBuffer)) + throw new ApplicationException("Invalid checksum. File has been modified."); + var decrypted = decrypt(encrypted, iv, streamsBuffer); + if (BitConverter.ToInt16(decrypted, 0) != 0x6FD6) + throw new ApplicationException("Invalid magic"); + return decrypted; + } + + uint getEncryptedHeaderOffset(IList sections) { + for (int i = sections.Count - 1; i >= 0; i--) { + var section = sections[i]; + if (getSectionNameHash(section) == (uint)key1) + return section.pointerToRawData; + } + throw new ApplicationException("Could not find encrypted section"); + } + + static byte[] getStreamsBuffer(PeImage peImage) { + var memStream = new MemoryStream(); + var writer = new BinaryWriter(memStream); + var reader = peImage.Reader; + foreach (var mdStream in peImage.Cor20Header.metadata.Streams) { + reader.BaseStream.Position = mdStream.Offset; + writer.Write(reader.ReadBytes((int)mdStream.length)); + } + return memStream.ToArray(); + } + + static ulong calcChecksum(byte[] data) { + var sum = DeobUtils.md5Sum(data); + return BitConverter.ToUInt64(sum, 0) ^ BitConverter.ToUInt64(sum, 8); + } + + static uint getSectionNameHash(SectionHeader section) { + uint hash = 0; + foreach (var c in section.name) + hash += c; + return hash; + } + + byte[] decrypt(byte[] encrypted, byte[] iv, byte[] streamsBuffer) { + var decrypted = DeobUtils.aesDecrypt(encrypted, DeobUtils.sha256Sum(streamsBuffer), iv); + var sha = SHA512.Create(); + var hash = sha.ComputeHash(streamsBuffer); + for (int i = 0; i < decrypted.Length; i += 64) { + int j; + for (j = 0; j < 64 && i + j < decrypted.Length; j++) + decrypted[i + j] ^= (byte)(hash[j] ^ key6); + hash = sha.ComputeHash(decrypted, i, j); + } + return decrypted; + } + } +}