/* 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; namespace de4dot.code.deobfuscators.MaxtoCode { class Decrypter6 { readonly uint[] key; readonly byte[] gen1 = new byte[0x100]; readonly byte[] gen2 = new byte[0x100]; readonly byte[] gen3 = new byte[0x100]; readonly byte[] gen4 = new byte[0x100]; static readonly byte[] d1 = new byte[16] { 14, 4, 13, 21, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7 }; static readonly byte[] d2 = new byte[16] { 15, 1, 8, 14, 6, 11, 3, 4, 30, 7, 2, 13, 12, 0, 5, 10 }; static readonly byte[] d3 = new byte[16] { 10, 0, 9, 14, 6, 3, 15, 5, 23, 13, 12, 7, 11, 4, 2, 8 }; static readonly byte[] d4 = new byte[16] { 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15 }; static readonly byte[] d5 = new byte[16] { 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9 }; static readonly byte[] d6 = new byte[16] { 12, 1, 10, 15, 9, 2, 6, 8, 2, 13, 3, 4, 14, 7, 5, 11 }; static readonly byte[] d7 = new byte[16] { 4, 11, 12, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1 }; static readonly byte[] d8 = new byte[16] { 13, 2, 8, 14, 6, 7, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7 }; public static byte[] decrypt(byte[] key, byte[] encrypted) { return new Decrypter6(key).decrypt(encrypted); } Decrypter6(byte[] key) { if (key.Length != 32) throw new ArgumentException("Invalid key size", "key"); this.key = new uint[8]; Buffer.BlockCopy(key, 0, this.key, 0, key.Length); initialize(); } byte[] decrypt(byte[] encrypted) { if ((encrypted.Length & 7) != 0) throw new ArgumentException("Invalid data length", "encrypted"); var decrypted = new byte[encrypted.Length]; int count = decrypted.Length / 8; for (int i = 0; i < count; i++) { uint x, y; decrypt(BitConverter.ToUInt32(encrypted, i * 8), BitConverter.ToUInt32(encrypted, i * 8 + 4), out x, out y); for (int j = 1; j < 100; j++) decrypt(x, y, out x, out y); writeUInt32(decrypted, i * 8, x); writeUInt32(decrypted, i * 8 + 4, y); } return decrypted; } static void writeUInt32(byte[] data, int index, uint value) { data[index] = (byte)value; data[index + 1] = (byte)(value >> 8); data[index + 2] = (byte)(value >> 16); data[index + 3] = (byte)(value >> 24); } void initialize() { for (int i = 0; i < 0x100; i++) { gen1[i] = (byte)((d1[i / 16] << 4) | d2[i & 0x0F]); gen2[i] = (byte)((d3[i / 16] << 4) | d4[i & 0x0F]); gen3[i] = (byte)((d5[i / 16] << 4) | d6[i & 0x0F]); gen4[i] = (byte)((d7[i / 16] << 4) | d8[i & 0x0F]); } } void decrypt(uint i0, uint i1, out uint o0, out uint o1) { uint x = i0; uint y = decrypt(x + key[0]); y ^= i1; x ^= decrypt(y + key[1]); y ^= decrypt(x + key[2]); x ^= decrypt(y + key[3]); y ^= decrypt(x + key[4]); x ^= decrypt(y + key[5]); y ^= decrypt(x + key[6]); x ^= decrypt(y + key[7]); for (int i = 0; i < 3; i++) { y ^= decrypt(x + key[7]); x ^= decrypt(y + key[6]); y ^= decrypt(x + key[5]); x ^= decrypt(y + key[4]); y ^= decrypt(x + key[3]); x ^= decrypt(y + key[2]); y ^= decrypt(x + key[1]); x ^= decrypt(y + key[0]); } o0 = y; o1 = x; } uint decrypt(uint val) { uint x = (uint)((gen1[(byte)(val >> 24)] << 24) | (gen2[(byte)(val >> 16)] << 16) | (gen3[(byte)(val >> 8)] << 8) | gen4[(byte)val]); return ror(x, 21); } static uint ror(uint val, int n) { return (val << (32 - n)) + (val >> n); } } }